diff --git a/packages/apidom-ls/src/config/codes.ts b/packages/apidom-ls/src/config/codes.ts index 22ab89a387..7f6d20a3a4 100644 --- a/packages/apidom-ls/src/config/codes.ts +++ b/packages/apidom-ls/src/config/codes.ts @@ -748,6 +748,22 @@ enum ApilintCodes { OPENAPI3_0_OAUTH_FLOWS_FIELD_CLIENT_CREDENTIALS_TYPE = 5210300, OPENAPI3_0_OAUTH_FLOWS_FIELD_AUTHORIZATION_CODE_TYPE = 5210400, + OPENAPI3_0_OAUTH_FLOW = 5220000, + OPENAPI3_0_OAUTH_FLOW_FIELD_AUTHORIZATION_URL_FORMAT_URI = 5220100, + OPENAPI3_0_OAUTH_FLOW_FIELD_AUTHORIZATION_URL_REQUIRED, + OPENAPI3_0_OAUTH_FLOW_FIELD_TOKEN_URL_FORMAT_URI = 5220200, + OPENAPI3_0_OAUTH_FLOW_FIELD_TOKEN_URL_REQUIRED, + OPENAPI3_0_OAUTH_FLOW_FIELD_REFRESH_URL_FORMAT_URI = 5220300, + OPENAPI3_0_OAUTH_FLOW_FIELD_SCOPES_TYPE = 5220400, + OPENAPI3_0_OAUTH_FLOW_FIELD_SCOPES_REQUIRED, + + OPENAPI3_0_XML = 5230000, + OPENAPI3_0_XML_FIELD_NAME_TYPE = 5230100, + OPENAPI3_0_XML_FIELD_NAMESPACE_FORMAT_URI = 5230200, + OPENAPI3_0_XML_FIELD_PREFIX_TYPE = 5230300, + OPENAPI3_0_XML_FIELD_ATTRIBUTE_TYPE = 5230400, + OPENAPI3_0_XML_FIELD_WRAPPED_TYPE = 5230500, + OPENAPI3_1 = 7000000, OPENAPI3_1_OPENAPI_VALUE_PATTERN_3_1_0 = 7000100, diff --git a/packages/apidom-ls/src/config/openapi/oauth-flow/completion.ts b/packages/apidom-ls/src/config/openapi/oauth-flow/completion.ts new file mode 100644 index 0000000000..823c2fb2ad --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/oauth-flow/completion.ts @@ -0,0 +1,79 @@ +import { + ApidomCompletionItem, + CompletionFormat, + CompletionType, +} from '../../../apidom-language-types'; + +const completion: ApidomCompletionItem[] = [ + { + label: 'authorizationUrl', + insertText: 'authorizationUrl', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + '**REQUIRED**. The authorization URL to be used for this flow. This MUST be in the form of a URL.', + }, + 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' }, + ], + }, + { + label: 'tokenUrl', + insertText: 'tokenUrl', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + '**REQUIRED**. The token URL to be used for this flow. This MUST be in the form of a URL.', + }, + 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' }, + ], + }, + { + label: 'refreshUrl', + insertText: 'refreshUrl ', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL.', + }, + 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' }, + ], + }, + { + label: 'scopes', + insertText: 'scopes ', + kind: 14, + format: CompletionFormat.OBJECT, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + '**REQUIRED**. The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. The map MAY be empty.', + }, + }, +]; + +export default completion; diff --git a/packages/apidom-ls/src/config/openapi/oauth-flow/documentation.ts b/packages/apidom-ls/src/config/openapi/oauth-flow/documentation.ts index 493e3c7730..bffa7a3891 100644 --- a/packages/apidom-ls/src/config/openapi/oauth-flow/documentation.ts +++ b/packages/apidom-ls/src/config/openapi/oauth-flow/documentation.ts @@ -1,14 +1,44 @@ const documentation = [ + { + target: 'authorizationUrl', + docs: 'Applies to `oauth2` (`"implicit"`, `"authorizationCode"`). **REQUIRED**. The authorization URL to be used for this flow. This MUST be in the form of a URL.', + 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' }, + ], + }, { target: 'authorizationUrl', docs: 'Applies to `oauth2` (`"implicit"`, `"authorizationCode"`). **REQUIRED**. The authorization URL to be used for this flow. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS.', targetSpecs: [{ namespace: 'openapi', version: '3.1.0' }], }, + { + target: 'tokenUrl', + docs: 'Applies to `oauth2` (`"password"`, `"clientCredentials"`, `"authorizationCode"`). **REQUIRED**. The token URL to be used for this flow. This MUST be in the form of a URL.', + 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' }, + ], + }, { target: 'tokenUrl', docs: 'Applies to `oauth2` (`"password"`, `"clientCredentials"`, `"authorizationCode"`). **REQUIRED**. The token URL to be used for this flow. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS.', targetSpecs: [{ namespace: 'openapi', version: '3.1.0' }], }, + { + target: 'refreshUrl', + docs: 'Applies to `oauth2`. The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL.', + 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' }, + ], + }, { target: 'refreshUrl', docs: 'Applies to `oauth2`. The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS.', @@ -18,6 +48,15 @@ const documentation = [ target: 'scopes', docs: 'Map[`string`, `string`]\n\\\n\\\nApplies to `oauth2`. **REQUIRED**. The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. The map MAY be empty.', }, + { + docs: '#### [OAuth Flow Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oauth-flow-object)\n\nConfiguration details for a supported OAuth Flow\n\n##### Fixed Fields\nField Name | Type | Applies To | Description\n---|:---:|---|---\nauthorizationUrl | `string` | `oauth2` (`"implicit"`, `"authorizationCode"`) | **REQUIRED**. The authorization URL to be used for this flow. This MUST be in the form of a URL.\ntokenUrl | `string` | `oauth2` (`"password"`, `"clientCredentials"`, `"authorizationCode"`) | **REQUIRED**. The token URL to be used for this flow. This MUST be in the form of a URL.\nrefreshUrl | `string` | `oauth2` | The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL.\nscopes | Map[`string`, `string`] | `oauth2` | **REQUIRED**. The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. The map MAY be empty.\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##### OAuth Flow Object Examples\n\n```JSON\n{\n "type": "oauth2",\n "flows": {\n "implicit": {\n "authorizationUrl": "https://example.com/api/oauth/dialog",\n "scopes": {\n "write:pets": "modify pets in your account",\n "read:pets": "read your pets"\n }\n },\n "authorizationCode": {\n "authorizationUrl": "https://example.com/api/oauth/dialog",\n "tokenUrl": "https://example.com/api/oauth/token",\n "scopes": {\n "write:pets": "modify pets in your account",\n "read:pets": "read your pets"\n }\n }\n }\n}\n```\n\n\n\\\nYAML\n```yaml\ntype: oauth2\nflows:\n implicit:\n authorizationUrl: https://example.com/api/oauth/dialog\n scopes:\n write:pets: modify pets in your account\n read:pets: read your pets\n authorizationCode:\n authorizationUrl: https://example.com/api/oauth/dialog\n tokenUrl: https://example.com/api/oauth/token\n scopes:\n write:pets: modify pets in your account\n read:pets: read your pets\n```', + 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' }, + ], + }, { docs: '#### [OAuth Flow Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#oauthFlowObject)\n\nConfiguration details for a supported OAuth Flow\n##### Fixed Fields\nField Name | Type | Applies To | Description\n---|:---:|---|:---\nauthorizationUrl | `string` | `oauth2` (`"implicit"`, `"authorizationCode"`) | **REQUIRED**. The authorization URL to be used for this flow. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS.\ntokenUrl | `string` | `oauth2` (`"password"`, `"clientCredentials"`, `"authorizationCode"`) | **REQUIRED**. The token URL to be used for this flow. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS.\nrefreshUrl | `string` | `oauth2` | The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS.\nscopes | Map[`string`, `string`] | `oauth2` | **REQUIRED**. The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. The map MAY be empty.\n\n\\\nThis object MAY be extended with [Specification Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specificationExtensions).\n##### OAuth Flow Object Examples\n\n\\\nJSON\n```json\n{\n "type": "oauth2",\n "flows": {\n "implicit": {\n "authorizationUrl": "https://example.com/api/oauth/dialog",\n "scopes": {\n "write:pets": "modify pets in your account",\n "read:pets": "read your pets"\n }\n },\n "authorizationCode": {\n "authorizationUrl": "https://example.com/api/oauth/dialog",\n "tokenUrl": "https://example.com/api/oauth/token",\n "scopes": {\n "write:pets": "modify pets in your account",\n "read:pets": "read your pets"\n }\n }\n }\n}\n```\n\n\n\\\nYAML\n```yaml\ntype: oauth2\nflows: \n implicit:\n authorizationUrl: https://example.com/api/oauth/dialog\n scopes:\n write:pets: modify pets in your account\n read:pets: read your pets\n authorizationCode:\n authorizationUrl: https://example.com/api/oauth/dialog\n tokenUrl: https://example.com/api/oauth/token\n scopes:\n write:pets: modify pets in your account\n read:pets: read your pets\n```\n', targetSpecs: [{ namespace: 'openapi', version: '3.1.0' }], diff --git a/packages/apidom-ls/src/config/openapi/oauth-flow/lint/allowed-fields.ts b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/allowed-fields.ts new file mode 100644 index 0000000000..2c6c2fe290 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/allowed-fields.ts @@ -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: [['authorizationUrl', 'tokenUrl', 'refreshUrl', 'scopes'], 'x-'], + marker: 'key', +}; + +export default allowedFieldsLint; diff --git a/packages/apidom-ls/src/config/openapi/oauth-flow/lint/authorization-url--format-uri.ts b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/authorization-url--format-uri.ts new file mode 100644 index 0000000000..c50edcbe60 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/authorization-url--format-uri.ts @@ -0,0 +1,15 @@ +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; + +const authorizationUrlFormatURILint: LinterMeta = { + code: ApilintCodes.OPENAPI3_0_OAUTH_FLOW_FIELD_AUTHORIZATION_URL_FORMAT_URI, + source: 'apilint', + message: "'authorizationUrl' value must be a valid URL", + severity: 1, + linterFunction: 'apilintValidURI', + marker: 'value', + target: 'authorizationUrl', + data: {}, +}; + +export default authorizationUrlFormatURILint; diff --git a/packages/apidom-ls/src/config/openapi/oauth-flow/lint/authorization-url--required.ts b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/authorization-url--required.ts new file mode 100644 index 0000000000..526b6fdf8b --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/authorization-url--required.ts @@ -0,0 +1,24 @@ +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; + +const authorizationUrlRequiredLint: LinterMeta = { + code: ApilintCodes.OPENAPI3_0_OAUTH_FLOW_FIELD_AUTHORIZATION_URL_REQUIRED, + source: 'apilint', + message: "should always have a 'authorizationUrl'", + severity: 1, + linterFunction: 'hasRequiredField', + linterParams: ['authorizationUrl'], + marker: 'key', + data: { + quickFix: [ + { + message: "add 'authorizationUrl' field", + action: 'addChild', + snippetYaml: 'authorizationUrl: \n ', + snippetJson: '"authorizationUrl": "",\n ', + }, + ], + }, +}; + +export default authorizationUrlRequiredLint; diff --git a/packages/apidom-ls/src/config/openapi/oauth-flow/lint/index.ts b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/index.ts new file mode 100644 index 0000000000..e7ef22a219 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/index.ts @@ -0,0 +1,21 @@ +import authorizationUrlFormatURILint from './authorization-url--format-uri'; +import authorizationUrlRequiredLint from './authorization-url--required'; +import tokenUrlFormatURILint from './token-url--format-uri'; +import tokenUrlRequiredLint from './token-url--required'; +import refreshUrlFormatURILint from './refresh-url--format-uri'; +import scopesTypeLint from './scopes--type'; +import scopesRequiredLint from './scopes--required'; +import allowedFieldsLint from './allowed-fields'; + +const lints = [ + authorizationUrlFormatURILint, + authorizationUrlRequiredLint, + tokenUrlFormatURILint, + tokenUrlRequiredLint, + refreshUrlFormatURILint, + scopesTypeLint, + scopesRequiredLint, + allowedFieldsLint, +]; + +export default lints; diff --git a/packages/apidom-ls/src/config/openapi/oauth-flow/lint/refresh-url--format-uri.ts b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/refresh-url--format-uri.ts new file mode 100644 index 0000000000..f4a1c23049 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/refresh-url--format-uri.ts @@ -0,0 +1,15 @@ +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; + +const refreshUrlFormatURILint: LinterMeta = { + code: ApilintCodes.OPENAPI3_0_OAUTH_FLOW_FIELD_REFRESH_URL_FORMAT_URI, + source: 'apilint', + message: "'refreshUrl' value must be a valid URL", + severity: 1, + linterFunction: 'apilintValidURI', + marker: 'value', + target: 'refreshUrl', + data: {}, +}; + +export default refreshUrlFormatURILint; diff --git a/packages/apidom-ls/src/config/openapi/oauth-flow/lint/scopes--required.ts b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/scopes--required.ts new file mode 100644 index 0000000000..b198c48b6e --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/scopes--required.ts @@ -0,0 +1,24 @@ +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; + +const scopesRequiredLint: LinterMeta = { + code: ApilintCodes.OPENAPI3_0_OAUTH_FLOW_FIELD_SCOPES_REQUIRED, + source: 'apilint', + message: "should always have a 'scopes'", + severity: 1, + linterFunction: 'hasRequiredField', + linterParams: ['scopes'], + marker: 'key', + data: { + quickFix: [ + { + message: "add 'scopes' field", + action: 'addChild', + snippetYaml: 'scopes: \n ', + snippetJson: '"scopes": {},\n ', + }, + ], + }, +}; + +export default scopesRequiredLint; diff --git a/packages/apidom-ls/src/config/openapi/oauth-flow/lint/scopes--type.ts b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/scopes--type.ts new file mode 100644 index 0000000000..77d1b21bed --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/scopes--type.ts @@ -0,0 +1,16 @@ +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; + +const scopesTypeLint: LinterMeta = { + code: ApilintCodes.OPENAPI3_0_OAUTH_FLOW_FIELD_SCOPES_TYPE, + source: 'apilint', + message: "'scopes' must be an object", + severity: 1, + linterFunction: 'apilintElementOrClass', + linterParams: ['oauth-flow-scopes'], + marker: 'value', + target: 'scopes', + data: {}, +}; + +export default scopesTypeLint; diff --git a/packages/apidom-ls/src/config/openapi/oauth-flow/lint/token-url--format-uri.ts b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/token-url--format-uri.ts new file mode 100644 index 0000000000..e631621ccf --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/token-url--format-uri.ts @@ -0,0 +1,15 @@ +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; + +const tokenUrlFormatURILint: LinterMeta = { + code: ApilintCodes.OPENAPI3_0_OAUTH_FLOW_FIELD_TOKEN_URL_FORMAT_URI, + source: 'apilint', + message: "'tokenUrl' value must be a valid URL", + severity: 1, + linterFunction: 'apilintValidURI', + marker: 'value', + target: 'tokenUrl', + data: {}, +}; + +export default tokenUrlFormatURILint; diff --git a/packages/apidom-ls/src/config/openapi/oauth-flow/lint/token-url--required.ts b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/token-url--required.ts new file mode 100644 index 0000000000..d9191f457b --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/oauth-flow/lint/token-url--required.ts @@ -0,0 +1,24 @@ +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; + +const tokenUrlRequiredLint: LinterMeta = { + code: ApilintCodes.OPENAPI3_0_OAUTH_FLOW_FIELD_TOKEN_URL_REQUIRED, + source: 'apilint', + message: "should always have a 'tokenUrl'", + severity: 1, + linterFunction: 'hasRequiredField', + linterParams: ['tokenUrl'], + marker: 'key', + data: { + quickFix: [ + { + message: "add 'tokenUrl' field", + action: 'addChild', + snippetYaml: 'tokenUrl: \n ', + snippetJson: '"tokenUrl": "",\n ', + }, + ], + }, +}; + +export default tokenUrlRequiredLint; diff --git a/packages/apidom-ls/src/config/openapi/oauth-flow/meta.ts b/packages/apidom-ls/src/config/openapi/oauth-flow/meta.ts index 33a6f79694..381bda653d 100644 --- a/packages/apidom-ls/src/config/openapi/oauth-flow/meta.ts +++ b/packages/apidom-ls/src/config/openapi/oauth-flow/meta.ts @@ -1,7 +1,11 @@ +import lint from './lint'; +import completion from './completion'; import documentation from './documentation'; import { FormatMeta } from '../../../apidom-language-types'; const meta: FormatMeta = { + lint, + completion, documentation, }; diff --git a/packages/apidom-ls/src/config/openapi/operation/lint/deprecated--type.ts b/packages/apidom-ls/src/config/openapi/operation/lint/deprecated--type.ts index 70914db155..9184b2d6e4 100644 --- a/packages/apidom-ls/src/config/openapi/operation/lint/deprecated--type.ts +++ b/packages/apidom-ls/src/config/openapi/operation/lint/deprecated--type.ts @@ -4,7 +4,7 @@ import { LinterMeta } from '../../../../apidom-language-types'; const deprecatedTypeLint: LinterMeta = { code: ApilintCodes.OPENAPI3_0_OPERATION_FIELD_DEPRECATED_TYPE, source: 'apilint', - message: 'deprecated must be a string', + message: 'deprecated must be a boolean', severity: 1, linterFunction: 'apilintType', linterParams: ['boolean'], diff --git a/packages/apidom-ls/src/config/openapi/xml/completion.ts b/packages/apidom-ls/src/config/openapi/xml/completion.ts new file mode 100644 index 0000000000..c5b22ec136 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/xml/completion.ts @@ -0,0 +1,80 @@ +import { + ApidomCompletionItem, + CompletionFormat, + CompletionType, +} from '../../../apidom-language-types'; + +const completion: ApidomCompletionItem[] = [ + { + label: 'name', + insertText: 'name', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + 'Replaces the name of the element/attribute used for the described schema property. When defined within `items`, it will affect the name of the individual XML elements within the list. When defined alongside `type` being `array` (outside the `items`), it will affect the wrapping element and only if `wrapped` is `true`. If `wrapped` is `false`, it will be ignored.', + }, + }, + { + label: 'namespace', + insertText: 'namespace', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: 'The URI of the namespace definition. This MUST be in the form of an absolute URI.', + }, + }, + { + label: 'prefix', + insertText: 'prefix ', + kind: 14, + format: CompletionFormat.QUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + 'The prefix to be used for the [name](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xmlName).', + }, + 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' }, + ], + }, + { + label: 'attribute', + insertText: 'attribute ', + kind: 14, + format: CompletionFormat.UNQUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + 'Declares whether the property definition translates to an attribute instead of an element. Default value is `false`.', + }, + }, + { + label: 'wrapped', + insertText: 'wrapped ', + kind: 14, + format: CompletionFormat.UNQUOTED, + type: CompletionType.PROPERTY, + insertTextFormat: 2, + documentation: { + kind: 'markdown', + value: + 'MAY be used only for an array definition. Signifies whether the array is wrapped (for example, ``) or unwrapped (``). Default value is `false`. The definition takes effect only when defined alongside `type` being `array` (outside the `items`).', + }, + }, +]; + +export default completion; diff --git a/packages/apidom-ls/src/config/openapi/xml/documentation.ts b/packages/apidom-ls/src/config/openapi/xml/documentation.ts index ceb90f02cd..e32a7d3cf6 100644 --- a/packages/apidom-ls/src/config/openapi/xml/documentation.ts +++ b/packages/apidom-ls/src/config/openapi/xml/documentation.ts @@ -7,6 +7,16 @@ const documentation = [ target: 'namespace', docs: 'The URI of the namespace definition. This MUST be in the form of an absolute URI.', }, + { + target: 'prefix', + docs: 'The prefix to be used for the [name](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xmlName).', + 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' }, + ], + }, { target: 'prefix', docs: 'The prefix to be used for the [name](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xmlName).', @@ -20,13 +30,22 @@ const documentation = [ target: 'wrapped', docs: 'MAY be used only for an array definition. Signifies whether the array is wrapped (for example, ``) or unwrapped (``). Default value is `false`. The definition takes effect only when defined alongside `type` being `array` (outside the `items`).', }, + /** + * The original documentation has been trimmed in this implementation for readability purposes + * A new custom section `Additional documentation topics` has been added, + * which adds external links back to the original documentation + */ + { + docs: '#### [XML Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xmlObject)\n\nA metadata object that allows for more fine-tuned XML model definitions.\n\nWhen using arrays, XML element names are *not* inferred (for singular/plural forms) and the `name` property SHOULD be used to add that information.\nSee examples for expected behavior.\n\n##### Fixed Fields\nField Name | Type | Description\n---|:---:|---\nname | `string` | Replaces the name of the element/attribute used for the described schema property. When defined within `items`, it will affect the name of the individual XML elements within the list. When defined alongside `type` being `array` (outside the `items`), it will affect the wrapping element and only if `wrapped` is `true`. If `wrapped` is `false`, it will be ignored.\nnamespace | `string` | The URI of the namespace definition. Value MUST be in the form of an absolute URI.\nprefix | `string` | The prefix to be used for the [name](#xmlName).\nattribute | `boolean` | Declares whether the property definition translates to an attribute instead of an element. Default value is `false`.\nwrapped | `boolean` | MAY be used only for an array definition. Signifies whether the array is wrapped (for example, ``) or unwrapped (``). Default value is `false`. The definition takes effect only when defined alongside `type` being `array` (outside the `items`).\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#### Additional documentation topics\n\n##### [XML Object Examples](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xml-object-examples)\nThe examples of the XML object definitions are included inside a property definition of a [Schema Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#schemaObject) with a sample of the XML representation of it.\n\n- [No XML Element](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#no-xml-element)\n- [XML Name Replacement](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xml-name-replacement)\n- [XML Attribute, Prefix and Namespace](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xml-attribute-prefix-and-namespace)\n- [XML Arrays](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xml-arrays)', + 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' }, + ], + }, { - /** - * The original documentation has been trimmed in this implementation for readability purposes - * A new custom section `Additional documentation topics` has been added, - * which adds external links back to the original documentation - */ - docs: '#### [XML Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xmlObject)\n\nA metadata object that allows for more fine-tuned XML model definitions.\n\nWhen using arrays, XML element names are *not* inferred (for singular/plural forms) and the `name` property SHOULD be used to add that information.\nSee examples for expected behavior.\n\n##### Fixed Fields\nField Name | Type | Description\n---|:---:|---\nname | `string` | Replaces the name of the element/attribute used for the described schema property. When defined within `items`, it will affect the name of the individual XML elements within the list. When defined alongside `type` being `array` (outside the `items`), it will affect the wrapping element and only if `wrapped` is `true`. If `wrapped` is `false`, it will be ignored.\nnamespace | `string` | The URI of the namespace definition. This MUST be in the form of an absolute URI.\nprefix | `string` | The prefix to be used for the [name](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xmlName).\nattribute | `boolean` | Declares whether the property definition translates to an attribute instead of an element. Default value is `false`.\nwrapped | `boolean` | MAY be used only for an array definition. Signifies whether the array is wrapped (for example, ``) or unwrapped (``). Default value is `false`. The definition takes effect only when defined alongside `type` being `array` (outside the `items`).\n\nThis object MAY be extended with [Specification Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specificationExtensions).\n\n\\\n#### Additional documentation topics\n\n##### [XML Object Examples](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xml-object-examples)\nThe examples of the XML object definitions are included inside a property definition of a [Schema Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#schemaObject) with a sample of the XML representation of it.\n\n- [No XML Element](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#no-xml-element)\n- [XML Name Replacement](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xml-name-replacement)\n- [XML Attribute, Prefix and Namespace](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xml-attribute-prefix-and-namespace)\n- [XML Arrays](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xml-arrays)\n', + docs: '#### [XML Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xmlObject)\n\nA metadata object that allows for more fine-tuned XML model definitions.\n\nWhen using arrays, XML element names are *not* inferred (for singular/plural forms) and the `name` property SHOULD be used to add that information.\nSee examples for expected behavior.\n\n##### Fixed Fields\nField Name | Type | Description\n---|:---:|---\nname | `string` | Replaces the name of the element/attribute used for the described schema property. When defined within `items`, it will affect the name of the individual XML elements within the list. When defined alongside `type` being `array` (outside the `items`), it will affect the wrapping element and only if `wrapped` is `true`. If `wrapped` is `false`, it will be ignored.\nnamespace | `string` | The URI of the namespace definition. This MUST be in the form of an absolute URI.\nprefix | `string` | The prefix to be used for the [name](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xmlName).\nattribute | `boolean` | Declares whether the property definition translates to an attribute instead of an element. Default value is `false`.\nwrapped | `boolean` | MAY be used only for an array definition. Signifies whether the array is wrapped (for example, ``) or unwrapped (``). Default value is `false`. The definition takes effect only when defined alongside `type` being `array` (outside the `items`).\n\nThis object MAY be extended with [Specification Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specificationExtensions).\n\n#### Additional documentation topics\n\n##### [XML Object Examples](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xml-object-examples)\nThe examples of the XML object definitions are included inside a property definition of a [Schema Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#schemaObject) with a sample of the XML representation of it.\n\n- [No XML Element](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#no-xml-element)\n- [XML Name Replacement](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xml-name-replacement)\n- [XML Attribute, Prefix and Namespace](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xml-attribute-prefix-and-namespace)\n- [XML Arrays](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xml-arrays)\n', targetSpecs: [{ namespace: 'openapi', version: '3.1.0' }], }, ]; diff --git a/packages/apidom-ls/src/config/openapi/xml/lint/allowed-fields.ts b/packages/apidom-ls/src/config/openapi/xml/lint/allowed-fields.ts new file mode 100644 index 0000000000..59b0537a47 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/xml/lint/allowed-fields.ts @@ -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: [['name', 'namespace', 'prefix', 'attribute', 'wrapped'], 'x-'], + marker: 'key', +}; + +export default allowedFieldsLint; diff --git a/packages/apidom-ls/src/config/openapi/xml/lint/attribute--type.ts b/packages/apidom-ls/src/config/openapi/xml/lint/attribute--type.ts new file mode 100644 index 0000000000..da2210351d --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/xml/lint/attribute--type.ts @@ -0,0 +1,16 @@ +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; + +const attributeTypeLint: LinterMeta = { + code: ApilintCodes.OPENAPI3_0_XML_FIELD_ATTRIBUTE_TYPE, + source: 'apilint', + message: 'attribute must be a boolean', + severity: 1, + linterFunction: 'apilintType', + linterParams: ['boolean'], + marker: 'value', + target: 'attribute', + data: {}, +}; + +export default attributeTypeLint; diff --git a/packages/apidom-ls/src/config/openapi/xml/lint/index.ts b/packages/apidom-ls/src/config/openapi/xml/lint/index.ts new file mode 100644 index 0000000000..9df0137bb3 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/xml/lint/index.ts @@ -0,0 +1,17 @@ +import allowedFieldsLint from './allowed-fields'; +import nameTypeLint from './name--type'; +import namespaceFormatURILint from './namespace--format-uri'; +import prefixTypeLint from './prefix--type'; +import attributeTypeLint from './attribute--type'; +import wrappedTypeLint from './wrapped--type'; + +const lints = [ + nameTypeLint, + namespaceFormatURILint, + prefixTypeLint, + attributeTypeLint, + wrappedTypeLint, + allowedFieldsLint, +]; + +export default lints; diff --git a/packages/apidom-ls/src/config/openapi/xml/lint/name--type.ts b/packages/apidom-ls/src/config/openapi/xml/lint/name--type.ts new file mode 100644 index 0000000000..0d0012b9c1 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/xml/lint/name--type.ts @@ -0,0 +1,16 @@ +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; + +const nameTypeLint: LinterMeta = { + code: ApilintCodes.OPENAPI3_0_XML_FIELD_NAME_TYPE, + source: 'apilint', + message: 'name must be a string', + severity: 1, + linterFunction: 'apilintType', + linterParams: ['string'], + marker: 'value', + target: 'name', + data: {}, +}; + +export default nameTypeLint; diff --git a/packages/apidom-ls/src/config/openapi/xml/lint/namespace--format-uri.ts b/packages/apidom-ls/src/config/openapi/xml/lint/namespace--format-uri.ts new file mode 100644 index 0000000000..3e3c8a5185 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/xml/lint/namespace--format-uri.ts @@ -0,0 +1,16 @@ +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; + +const namespaceFormatURILint: LinterMeta = { + code: ApilintCodes.OPENAPI3_0_XML_FIELD_NAMESPACE_FORMAT_URI, + source: 'apilint', + message: 'namespace MUST be in the format of an absolute URL.', + severity: 1, + linterFunction: 'apilintValidURI', + linterParams: [true], + marker: 'value', + target: 'namespace', + data: {}, +}; + +export default namespaceFormatURILint; diff --git a/packages/apidom-ls/src/config/openapi/xml/lint/prefix--type.ts b/packages/apidom-ls/src/config/openapi/xml/lint/prefix--type.ts new file mode 100644 index 0000000000..a4859bd286 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/xml/lint/prefix--type.ts @@ -0,0 +1,16 @@ +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; + +const prefixTypeLint: LinterMeta = { + code: ApilintCodes.OPENAPI3_0_XML_FIELD_PREFIX_TYPE, + source: 'apilint', + message: 'prefix must be a string', + severity: 1, + linterFunction: 'apilintType', + linterParams: ['string'], + marker: 'value', + target: 'prefix', + data: {}, +}; + +export default prefixTypeLint; diff --git a/packages/apidom-ls/src/config/openapi/xml/lint/wrapped--type.ts b/packages/apidom-ls/src/config/openapi/xml/lint/wrapped--type.ts new file mode 100644 index 0000000000..22bb385840 --- /dev/null +++ b/packages/apidom-ls/src/config/openapi/xml/lint/wrapped--type.ts @@ -0,0 +1,16 @@ +import ApilintCodes from '../../../codes'; +import { LinterMeta } from '../../../../apidom-language-types'; + +const wrappedTypeLint: LinterMeta = { + code: ApilintCodes.OPENAPI3_0_XML_FIELD_WRAPPED_TYPE, + source: 'apilint', + message: 'wrapped must be a boolean', + severity: 1, + linterFunction: 'apilintType', + linterParams: ['boolean'], + marker: 'value', + target: 'wrapped', + data: {}, +}; + +export default wrappedTypeLint; diff --git a/packages/apidom-ls/src/config/openapi/xml/meta.ts b/packages/apidom-ls/src/config/openapi/xml/meta.ts index 33a6f79694..381bda653d 100644 --- a/packages/apidom-ls/src/config/openapi/xml/meta.ts +++ b/packages/apidom-ls/src/config/openapi/xml/meta.ts @@ -1,7 +1,11 @@ +import lint from './lint'; +import completion from './completion'; import documentation from './documentation'; import { FormatMeta } from '../../../apidom-language-types'; const meta: FormatMeta = { + lint, + completion, documentation, }; diff --git a/packages/apidom-ls/src/services/validation/linter-functions.ts b/packages/apidom-ls/src/services/validation/linter-functions.ts index 5c34021071..6e90a8f994 100644 --- a/packages/apidom-ls/src/services/validation/linter-functions.ts +++ b/packages/apidom-ls/src/services/validation/linter-functions.ts @@ -494,14 +494,14 @@ export const standardLinterfunctions: FunctionItem[] = [ }, { functionName: 'apilintValidURI', - function: (element: Element): boolean => { + function: (element: Element, absolute = false): boolean => { if (element) { if (!isString(element)) { return false; } try { // eslint-disable-next-line no-new - new URL(element.toValue(), 'http://example.com'); + new URL(element.toValue(), absolute ? undefined : 'http://example.com'); } catch (e) { return false; }