Skip to content

Commit f9452f3

Browse files
authored
feat(ls): add option to pass refractor plugins (#5003)
1 parent dadedad commit f9452f3

File tree

14 files changed

+449
-19
lines changed

14 files changed

+449
-19
lines changed

packages/apidom-ls/README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@ The capabilities of the ApiDOM Language Service can be extended by providing cus
3737
```ts
3838
import { DocumentLink } from 'vscode-languageserver-types';
3939
import { TextDocument } from 'vscode-languageserver-textdocument';
40-
import { Element } from '@swagger-api/apidom-core';
40+
import {
41+
Element,
42+
MemberElement,
43+
isStringElement,
44+
} from "@swagger-api/apidom-core";
45+
import { InfoElement } from '@swagger-api/apidom-ns-asyncapi-2';
4146
import { getLanguageService, LinksProvider, config } from '@swagger-api/apidom-ls';
4247
import type {
4348
LanguageSettings,
@@ -161,13 +166,31 @@ customMetadata.rules = {
161166
},
162167
};
163168

169+
// Defining custom refractor plugins
170+
171+
const refractorPlugin = () => () => ({
172+
visitor: {
173+
MemberElement(element: MemberElement) {
174+
if (
175+
isStringElement(element.key) &&
176+
element.key.equals("additionalInfo")
177+
) {
178+
element.value = InfoElement.refract(element.value);
179+
}
180+
},
181+
},
182+
});
183+
164184
// Initializing ApiDOM Language Service with custom configuration
165185

166186
const refLinksProvider = new RefLinksProvider();
167187

168188
const customContext = {
169189
metadata: customMetadata,
170190
linksProviders: [refLinksProvider],
191+
refractorPlugins: {
192+
'asyncapi-2': [refractorPlugin()],
193+
}
171194
};
172195

173196
const languageService = getLanguageService(customContext);

packages/apidom-ls/src/apidom-language-service.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,15 @@ export default function getLanguageService(context: LanguageServiceContext): Lan
6464
metadata = context.metadata;
6565
}
6666
const documentCache = getDocumentCache<ParseResultElement>(10, 60, (document) =>
67-
parse(document, metadata.metadataMaps, true, true, true, context.defaultContentLanguage),
67+
parse(
68+
document,
69+
metadata.metadataMaps,
70+
true,
71+
true,
72+
true,
73+
context.defaultContentLanguage,
74+
context.refractorPlugins,
75+
),
6876
);
6977

7078
const languageSettings: LanguageSettings = {

packages/apidom-ls/src/apidom-language-types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ export interface LanguageServiceContext {
106106
symbolsContext?: SymbolsContext;
107107
colorsContext?: ColorsContext;
108108
linksContext?: LinksContext;
109+
refractorPlugins?: RefractorPlugins;
109110
}
110111

111112
/**
@@ -387,6 +388,11 @@ export interface LinksContext {
387388
modifierFunction?: LinksModifierFunction;
388389
}
389390

391+
/**
392+
* @public
393+
*/
394+
export type RefractorPlugins = Record<string, (() => unknown)[]>;
395+
390396
/**
391397
* @public
392398
*/

packages/apidom-ls/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export type {
6161
LinterFunction,
6262
LinterConditionTarget,
6363
DocumentationMeta,
64+
RefractorPlugins,
6465
} from './apidom-language-types.ts';
6566

6667
export {

packages/apidom-ls/src/parser-factory.ts

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { TextDocument } from 'vscode-languageserver-textdocument';
1818
import { ParseResultElement } from '@swagger-api/apidom-core';
1919

2020
import { setMetadataMap, findNamespace } from './utils/utils.ts';
21-
import { ContentLanguage, MetadataMaps } from './apidom-language-types.ts';
21+
import { ContentLanguage, MetadataMaps, RefractorPlugins } from './apidom-language-types.ts';
2222

2323
export interface ParserOptions {
2424
sourceMap?: boolean;
@@ -33,74 +33,119 @@ export async function parse(
3333
freeze = true,
3434
setMetadata = true,
3535
defaultContentLanguage?: ContentLanguage,
36+
refractorPlugins?: RefractorPlugins,
3637
): Promise<ParseResultElement> {
3738
// TODO improve detection mechanism
3839
const text: string = typeof textDocument === 'string' ? textDocument : textDocument.getText();
3940
let result;
4041
const contentLanguage = await findNamespace(text, defaultContentLanguage);
4142
if (contentLanguage.namespace === 'asyncapi' && contentLanguage.format === 'JSON') {
42-
result = await asyncapi2AdapterJson.parse(text, { sourceMap: true });
43+
const options: Record<string, unknown> = {
44+
sourceMap: true,
45+
refractorOpts: {
46+
plugins: [...(refractorPlugins?.['asyncapi-2'] || [])],
47+
},
48+
};
49+
50+
result = await asyncapi2AdapterJson.parse(text, options);
4351
} else if (contentLanguage.namespace === 'asyncapi' && contentLanguage.format === 'YAML') {
4452
const options: Record<string, unknown> = {
4553
sourceMap: true,
54+
refractorOpts: {
55+
plugins: [
56+
registerPlugins && refractorPluginReplaceEmptyElementAsyncAPI2(),
57+
...(refractorPlugins?.['asyncapi-2'] || []),
58+
].filter(Boolean),
59+
},
4660
};
47-
if (registerPlugins) {
48-
options.refractorOpts = { plugins: [refractorPluginReplaceEmptyElementAsyncAPI2()] };
49-
}
61+
5062
result = await asyncapi2AdapterYaml.parse(text, options);
5163
} else if (
5264
contentLanguage.namespace === 'openapi' &&
5365
contentLanguage.version === '2.0' &&
5466
contentLanguage.format === 'JSON'
5567
) {
56-
result = await openapi2AdapterJson.parse(text, { sourceMap: true });
68+
const options: Record<string, unknown> = {
69+
sourceMap: true,
70+
refractorOpts: {
71+
plugins: [...(refractorPlugins?.['openapi-2'] || [])],
72+
},
73+
};
74+
75+
result = await openapi2AdapterJson.parse(text, options);
5776
} else if (
5877
contentLanguage.namespace === 'openapi' &&
5978
contentLanguage.version === '2.0' &&
6079
contentLanguage.format === 'YAML'
6180
) {
6281
const options: Record<string, unknown> = {
6382
sourceMap: true,
83+
refractorOpts: {
84+
plugins: [
85+
registerPlugins && refractorPluginReplaceEmptyElementOpenAPI2(),
86+
...(refractorPlugins?.['openapi-2'] || []),
87+
].filter(Boolean),
88+
},
6489
};
65-
if (registerPlugins) {
66-
options.refractorOpts = { plugins: [refractorPluginReplaceEmptyElementOpenAPI2()] };
67-
}
90+
6891
result = await openapi2AdapterYaml.parse(text, options);
6992
} else if (
7093
contentLanguage.namespace === 'openapi' &&
7194
contentLanguage.version?.startsWith('3.0') &&
7295
contentLanguage.format === 'JSON'
7396
) {
74-
result = await openapi3_0AdapterJson.parse(text, { sourceMap: true });
97+
const options: Record<string, unknown> = {
98+
sourceMap: true,
99+
refractorOpts: {
100+
plugins: [...(refractorPlugins?.['openapi-3-0'] || [])],
101+
},
102+
};
103+
104+
result = await openapi3_0AdapterJson.parse(text, options);
75105
} else if (
76106
contentLanguage.namespace === 'openapi' &&
77107
contentLanguage.version?.startsWith('3.0') &&
78108
contentLanguage.format === 'YAML'
79109
) {
80110
const options: Record<string, unknown> = {
81111
sourceMap: true,
112+
refractorOpts: {
113+
plugins: [
114+
registerPlugins && refractorPluginReplaceEmptyElementOpenAPI3_0(),
115+
...(refractorPlugins?.['openapi-3-0'] || []),
116+
].filter(Boolean),
117+
},
82118
};
83-
if (registerPlugins) {
84-
options.refractorOpts = { plugins: [refractorPluginReplaceEmptyElementOpenAPI3_0()] };
85-
}
119+
86120
result = await openapi3_0AdapterYaml.parse(text, options);
87121
} else if (
88122
contentLanguage.namespace === 'openapi' &&
89123
contentLanguage.version?.startsWith('3.1') &&
90124
contentLanguage.format === 'JSON'
91125
) {
92-
result = await openapi3_1AdapterJson.parse(text, { sourceMap: true });
126+
const options: Record<string, unknown> = {
127+
sourceMap: true,
128+
refractorOpts: {
129+
plugins: [...(refractorPlugins?.['openapi-3-1'] || [])],
130+
},
131+
};
132+
133+
result = await openapi3_1AdapterJson.parse(text, options);
93134
} else if (
94135
contentLanguage.namespace === 'openapi' &&
95136
contentLanguage.version?.startsWith('3.1') &&
96137
contentLanguage.format === 'YAML'
97138
) {
98139
const options: Record<string, unknown> = {
99140
sourceMap: true,
141+
refractorOpts: {
142+
plugins: [
143+
registerPlugins && refractorPluginReplaceEmptyElementOpenAPI3_1(),
144+
...(refractorPlugins?.['openapi-3-1'] || []),
145+
].filter(Boolean),
146+
},
100147
};
101-
if (registerPlugins) {
102-
options.refractorOpts = { plugins: [refractorPluginReplaceEmptyElementOpenAPI3_1()] };
103-
}
148+
104149
result = await openapi3_1AdapterYaml.parse(text, options);
105150
} else if (contentLanguage.namespace === 'ads' && contentLanguage.format === 'JSON') {
106151
result = await adsAdapterJson.parse(text, { sourceMap: true });
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"asyncapi": "2.6.0",
3+
"info": {
4+
"title": "Test",
5+
"version": "1.0.0"
6+
},
7+
"channels": {},
8+
"additionalInfo": {
9+
"title": "Additional Info Test"
10+
}
11+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
asyncapi: '2.6.0'
2+
info:
3+
title: Test
4+
version: '1.0.0'
5+
channels:
6+
additionalInfo:
7+
title: Additional Info Test
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"swagger": "2.0",
3+
"info": {
4+
"title": "Test",
5+
"version": "1.0.0"
6+
},
7+
"paths": {},
8+
"additionalInfo": {
9+
"title": "Additional Info Test"
10+
}
11+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
swagger: '2.0'
2+
info:
3+
title: Test
4+
version: 1.0.0
5+
paths:
6+
additionalInfo:
7+
title: Additional Info Test
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"openapi": "3.0.4",
3+
"info": {
4+
"title": "Test",
5+
"version": "1.0.0"
6+
},
7+
"paths": {},
8+
"additionalInfo": {
9+
"title": "Additional Info Test"
10+
}
11+
}

0 commit comments

Comments
 (0)