Skip to content

Commit 6884151

Browse files
authored
feat(validator-speclynx): expose parse result via toolbox (#209)
1 parent 5c41cd6 commit 6884151

File tree

8 files changed

+77
-5
lines changed

8 files changed

+77
-5
lines changed

packages/jentic-openapi-validator-speclynx/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,13 @@ if "dict" in validator.accepts():
197197
## Custom Plugins
198198

199199
Create custom validation plugins as ES modules (`.mjs` files). Plugins use the ApiDOM visitor pattern and receive
200-
a toolbox with dependencies and diagnostics array:
200+
a toolbox with dependencies, diagnostics array, and parse result:
201201

202202
```javascript
203203
// custom-plugin.mjs
204204

205205
export default (toolbox) => {
206-
const {diagnostics, deps} = toolbox;
206+
const {diagnostics, deps, parseResult} = toolbox;
207207
const {DiagnosticSeverity} = deps['vscode-languageserver-types'];
208208
const {toValue} = deps['@speclynx/apidom-core'];
209209

packages/jentic-openapi-validator-speclynx/src/jentic/apitools/openapi/validator/backends/speclynx/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def __init__(
6464
@speclynx/apidom-datamodel, @speclynx/apidom-json-path, @speclynx/apidom-json-pointer,
6565
@speclynx/apidom-traverse, and @speclynx/apidom-reference
6666
- diagnostics: Array to collect validation diagnostics
67+
- parseResult: The full ApiDOM parse result for accessing document metadata
6768
See resources/plugins/example-plugin.mjs.sample for plugin format.
6869
"""
6970
self.speclynx_path = speclynx_path

packages/jentic-openapi-validator-speclynx/src/jentic/apitools/openapi/validator/backends/speclynx/resources/plugins/example-plugin.mjs.sample

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,19 @@
66
*
77
* Plugin structure:
88
* - Must export a default function that accepts a toolbox object with:
9-
* - diagnostics: Array to collect validation diagnostics
109
* - deps: External dependencies (vscode-languageserver-types, @speclynx/apidom-core, etc.)
10+
* - diagnostics: Array to collect validation diagnostics
11+
* - parseResult: The full ApiDOM parse result for accessing document metadata
1112
* - Returns an object with pre/post hooks and a visitor property
1213
* - The visitor contains methods named after ApiDOM element types
1314
* - Each visitor method receives a path object with information about the current element
1415
* - path.node: The actual ApiDOM element being visited
1516
* - path.getPathKeys(): Returns the JSON path to the element
1617
*
1718
* @param {Object} toolbox - Plugin toolbox
18-
* @param {Array} toolbox.diagnostics - Array to collect validation diagnostics
1919
* @param {Object} toolbox.deps - External dependencies
20+
* @param {Array} toolbox.diagnostics - Array to collect validation diagnostics
21+
* @param {Object} toolbox.parseResult - The ApiDOM parse result
2022
*/
2123

2224
export default (toolbox) => {

packages/jentic-openapi-validator-speclynx/src/jentic/apitools/openapi/validator/backends/speclynx/resources/plugins/openapi-document.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
* @speclynx/apidom-datamodel, @speclynx/apidom-json-path, @speclynx/apidom-json-pointer,
1313
* @speclynx/apidom-traverse, and @speclynx/apidom-reference
1414
* - diagnostics: Array to collect validation diagnostics
15+
* - parseResult: The full ApiDOM parse result for accessing document metadata
1516
*/
1617

1718
export default (toolbox) => {

packages/jentic-openapi-validator-speclynx/src/jentic/apitools/openapi/validator/backends/speclynx/resources/speclynx.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ async function validate(document, cliOptions) {
140140
return {valid: false, diagnostics};
141141
}
142142

143-
// Toolbox creation - provides deps and diagnostics to plugins
143+
// Toolbox creation - provides deps, diagnostics, and parseResult to plugins
144144
const createToolbox = () => ({
145145
deps: {
146146
'vscode-languageserver-types': vscodeLanguageServerTypes,
@@ -152,6 +152,7 @@ async function validate(document, cliOptions) {
152152
'@speclynx/apidom-reference': apidomReference,
153153
},
154154
diagnostics,
155+
parseResult,
155156
...createToolboxBase()
156157
});
157158

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Test plugin that verifies parseResult is available in the toolbox.
3+
*
4+
* This plugin emits a diagnostic if parseResult is missing or doesn't contain
5+
* expected properties, helping catch regressions in toolbox wiring.
6+
*/
7+
8+
export default (toolbox) => {
9+
const {diagnostics, deps, parseResult} = toolbox;
10+
const {DiagnosticSeverity} = deps['vscode-languageserver-types'];
11+
12+
return {
13+
visitor: {
14+
InfoElement() {
15+
// Verify parseResult is available
16+
if (!parseResult) {
17+
diagnostics.push({
18+
severity: DiagnosticSeverity.Error,
19+
message: 'toolbox.parseResult is missing',
20+
code: 'missing-parseresult',
21+
range: {
22+
start: {line: 0, character: 0},
23+
end: {line: 0, character: 0}
24+
},
25+
data: {path: []}
26+
});
27+
return;
28+
}
29+
30+
// For valid OpenAPI 3.x documents, parseResult.api should exist
31+
if (parseResult.api) {
32+
diagnostics.push({
33+
severity: DiagnosticSeverity.Information,
34+
message: 'parseResult.api is available',
35+
code: 'parseresult-api-available',
36+
range: {
37+
start: {line: 0, character: 0},
38+
end: {line: 0, character: 0}
39+
},
40+
data: {path: []}
41+
});
42+
}
43+
}
44+
}
45+
};
46+
};

packages/jentic-openapi-validator-speclynx/tests/fixtures/plugins/version-validator.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* @speclynx/apidom-datamodel, @speclynx/apidom-json-path, @speclynx/apidom-json-pointer,
77
* @speclynx/apidom-traverse, and @speclynx/apidom-reference
88
* - diagnostics: Array to collect validation diagnostics
9+
* - parseResult: The full ApiDOM parse result for accessing document metadata
910
*/
1011

1112
export default (toolbox) => {

packages/jentic-openapi-validator-speclynx/tests/test_speclynx_validate.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,26 @@ def test_both_default_and_custom_plugins_produce_diagnostics(
123123
# Custom plugin should detect integer version
124124
assert any("version" in d.message.lower() for d in result.diagnostics)
125125

126+
def test_parseresult_available_in_toolbox(self, speclynx_validator_with_plugins):
127+
"""Test that parseResult is available to plugins via toolbox.
128+
129+
The parseresult-check.mjs plugin emits an informational diagnostic
130+
when parseResult.api is available, verifying the toolbox wiring.
131+
"""
132+
document = {
133+
"openapi": "3.0.0",
134+
"info": {"title": "Test API", "version": "1.0.0"},
135+
"paths": {},
136+
}
137+
result = speclynx_validator_with_plugins.validate(document)
138+
assert result.valid is True
139+
# The parseresult-check plugin should emit info diagnostic confirming parseResult.api exists
140+
parseresult_diagnostic = next(
141+
(d for d in result.diagnostics if d.code == "parseresult-api-available"), None
142+
)
143+
assert parseresult_diagnostic is not None, "parseResult should be available to plugins"
144+
assert "parseResult.api is available" in parseresult_diagnostic.message
145+
126146
def test_validate_empty_document_produces_error(self, speclynx_validator, tmp_path):
127147
"""Test that empty documents produce validation errors.
128148

0 commit comments

Comments
 (0)