@swagger-api/apidom-parser-adapter-yaml-1-2 1.11.0 → 1.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,385 @@
1
+ import { ParseResultElement, ObjectElement, ArrayElement, MemberElement, AnnotationElement, CommentElement, isPrimitiveElement, createNamespace } from '@swagger-api/apidom-core';
2
+ import { formatFlowPlain, formatFlowSingleQuoted, formatFlowDoubleQuoted, formatBlockLiteral, formatBlockFolded } from '@swagger-api/apidom-ast';
3
+
4
+ /**
5
+ * @public
6
+ */
7
+
8
+ /**
9
+ * Thrown when the direct analysis encounters a YAML feature (tag, anchor, alias)
10
+ * that requires the full indirect two-pass analysis.
11
+ * @public
12
+ */
13
+ export class FallbackNeeded extends Error {
14
+ name = 'FallbackNeeded';
15
+ }
16
+
17
+ // YAML 1.2 Core Schema type detection — matches apidom-ast/yaml/schemas/json/* order:
18
+ // Null → Integer → FloatingPoint → Boolean
19
+ const NULL_RE = /^null$/;
20
+ const INT_RE = /^-?(0|[1-9][0-9]*)$/;
21
+ const FLOAT_RE = /^-?(0|[1-9][0-9]*)(\.[0-9]*)?([eE][-+]?[0-9]+)?$/;
22
+ const BOOL_RE = /^(true|false)$/;
23
+ function resolveScalarContent(s) {
24
+ if (NULL_RE.test(s)) return null;
25
+ if (INT_RE.test(s)) return parseInt(s, 10);
26
+ if (FLOAT_RE.test(s)) return parseFloat(s);
27
+ if (BOOL_RE.test(s)) return s === 'true';
28
+ return s;
29
+ }
30
+ function setSourceMap(element, cursor) {
31
+ // eslint-disable-next-line no-param-reassign
32
+ element.startPositionRow = cursor.startPosition.row;
33
+ // eslint-disable-next-line no-param-reassign
34
+ element.startPositionColumn = cursor.startPosition.column;
35
+ // eslint-disable-next-line no-param-reassign
36
+ element.startIndex = cursor.startIndex;
37
+ // eslint-disable-next-line no-param-reassign
38
+ element.endPositionRow = cursor.endPosition.row;
39
+ // eslint-disable-next-line no-param-reassign
40
+ element.endPositionColumn = cursor.endPosition.column;
41
+ // eslint-disable-next-line no-param-reassign
42
+ element.endIndex = cursor.endIndex;
43
+ }
44
+
45
+ /**
46
+ * Iterates named children of the current cursor node.
47
+ * Adds warning annotations for missing unnamed (structural) nodes.
48
+ * Restores cursor to parent when done.
49
+ */
50
+ const forEachNamedChild = (cursor, ctx, fn) => {
51
+ if (!cursor.gotoFirstChild()) return;
52
+ do {
53
+ if (!cursor.nodeIsNamed) {
54
+ if (cursor.nodeIsMissing) {
55
+ const ann = new AnnotationElement(`(Missing ${cursor.nodeType})`);
56
+ ann.classes.push('warning');
57
+ if (ctx.sourceMap) setSourceMap(ann, cursor);
58
+ ctx.annotations.push(ann);
59
+ }
60
+ } else {
61
+ var _cursor$currentFieldN;
62
+ fn(cursor, (_cursor$currentFieldN = cursor.currentFieldName) !== null && _cursor$currentFieldN !== void 0 ? _cursor$currentFieldN : null);
63
+ }
64
+ } while (cursor.gotoNextSibling());
65
+ cursor.gotoParent();
66
+ };
67
+ const walkFunctions = {
68
+ walkStream: (cursor, ctx) => {
69
+ const parseResult = new ParseResultElement();
70
+ if (ctx.sourceMap) setSourceMap(parseResult, cursor);
71
+ forEachNamedChild(cursor, ctx, child => {
72
+ const {
73
+ nodeType
74
+ } = child;
75
+ if (nodeType === 'document') {
76
+ const docContent = walkFunctions.walkDocument(child, ctx);
77
+ if (docContent !== null) parseResult.push(docContent);
78
+ } else if (nodeType === 'comment' && ctx.documentCount === 0) {
79
+ const comment = new CommentElement(child.nodeText);
80
+ if (ctx.sourceMap) setSourceMap(comment, child);
81
+ parseResult.push(comment);
82
+ } else if (nodeType === 'ERROR') {
83
+ walkFunctions.walkError(child, ctx);
84
+ }
85
+ });
86
+
87
+ // Mark the first content element as 'result' (matches YamlAstVisitor.stream.leave behaviour)
88
+ // @ts-ignore
89
+ const resultCandidates = parseResult.findElements(isPrimitiveElement);
90
+ if (resultCandidates.length > 0) {
91
+ resultCandidates[0].classes.push('result');
92
+ }
93
+ ctx.annotations.forEach(ann => parseResult.push(ann));
94
+ ctx.annotations = [];
95
+ return parseResult;
96
+ },
97
+ walkDocument: (cursor, ctx) => {
98
+ if (ctx.documentCount >= 1) {
99
+ if (ctx.documentCount === 1) {
100
+ const ann = new AnnotationElement('Only first document within YAML stream will be used. Rest will be discarded.');
101
+ ann.classes.push('warning');
102
+ if (ctx.sourceMap) setSourceMap(ann, cursor);
103
+ ctx.annotations.push(ann);
104
+ }
105
+ ctx.documentCount += 1;
106
+ return null;
107
+ }
108
+ ctx.documentCount += 1;
109
+ let content = null;
110
+ forEachNamedChild(cursor, ctx, child => {
111
+ const {
112
+ nodeType
113
+ } = child;
114
+ if (nodeType === 'tag' || nodeType === 'anchor' || nodeType === 'alias') {
115
+ throw new FallbackNeeded();
116
+ }
117
+ if (nodeType.endsWith('_directive') || nodeType === 'comment') return;
118
+ if (nodeType === 'ERROR') {
119
+ walkFunctions.walkError(child, ctx);
120
+ return;
121
+ }
122
+ const result = walkFunctions.walkNode(child, ctx);
123
+ if (result !== null) content = result;
124
+ });
125
+ return content;
126
+ },
127
+ walkMapping: (cursor, ctx) => {
128
+ const element = new ObjectElement();
129
+ if (ctx.sourceMap) setSourceMap(element, cursor);
130
+ forEachNamedChild(cursor, ctx, child => {
131
+ const {
132
+ nodeType
133
+ } = child;
134
+ if (nodeType === 'tag' || nodeType === 'anchor' || nodeType === 'alias') {
135
+ throw new FallbackNeeded();
136
+ }
137
+ if (nodeType === 'block_mapping_pair' || nodeType === 'flow_pair') {
138
+ element.push(walkFunctions.walkPair(child, ctx));
139
+ } else if (nodeType === 'ERROR') {
140
+ walkFunctions.walkError(child, ctx);
141
+ }
142
+ });
143
+ return element;
144
+ },
145
+ walkSequence: (cursor, ctx) => {
146
+ const element = new ArrayElement();
147
+ if (ctx.sourceMap) setSourceMap(element, cursor);
148
+ forEachNamedChild(cursor, ctx, child => {
149
+ const {
150
+ nodeType
151
+ } = child;
152
+ if (nodeType === 'tag' || nodeType === 'anchor' || nodeType === 'alias') {
153
+ throw new FallbackNeeded();
154
+ }
155
+ if (nodeType === 'ERROR') {
156
+ walkFunctions.walkError(child, ctx);
157
+ } else if (nodeType === 'block_sequence_item') {
158
+ const item = walkFunctions.walkSequenceItem(child, ctx);
159
+ if (item !== null) element.push(item);
160
+ } else {
161
+ // flow_sequence items (flow_node, flow_pair, scalars) appear directly
162
+ const item = walkFunctions.walkNode(child, ctx);
163
+ if (item !== null) element.push(item);
164
+ }
165
+ });
166
+ return element;
167
+ },
168
+ walkPair: (cursor, ctx) => {
169
+ const pairStartRow = cursor.startPosition.row;
170
+ const pairStartCol = cursor.startPosition.column;
171
+ const pairStartIdx = cursor.startIndex;
172
+ const pairEndRow = cursor.endPosition.row;
173
+ const pairEndCol = cursor.endPosition.column;
174
+ const pairEndIdx = cursor.endIndex;
175
+ let keyElement = null;
176
+ let valueElement = null;
177
+ forEachNamedChild(cursor, ctx, (child, fieldName) => {
178
+ const {
179
+ nodeType
180
+ } = child;
181
+ if (nodeType === 'tag' || nodeType === 'anchor' || nodeType === 'alias') {
182
+ throw new FallbackNeeded();
183
+ }
184
+ if (nodeType === 'ERROR') {
185
+ walkFunctions.walkError(child, ctx);
186
+ } else if (fieldName === 'key') {
187
+ keyElement = walkFunctions.walkNode(child, ctx);
188
+ } else if (fieldName === 'value') {
189
+ valueElement = walkFunctions.walkNode(child, ctx);
190
+ }
191
+ });
192
+ if (keyElement === null) {
193
+ keyElement = ctx.namespace.toElement('');
194
+ keyElement.classes.push('yaml-e-node');
195
+ keyElement.classes.push('yaml-e-scalar');
196
+ if (ctx.sourceMap) {
197
+ keyElement.startPositionRow = pairStartRow;
198
+ keyElement.startPositionColumn = pairStartCol;
199
+ keyElement.startIndex = pairStartIdx;
200
+ keyElement.endPositionRow = pairStartRow;
201
+ keyElement.endPositionColumn = pairStartCol;
202
+ keyElement.endIndex = pairStartIdx;
203
+ }
204
+ }
205
+ if (valueElement === null) {
206
+ valueElement = ctx.namespace.toElement('');
207
+ valueElement.classes.push('yaml-e-node');
208
+ valueElement.classes.push('yaml-e-scalar');
209
+ if (ctx.sourceMap) {
210
+ valueElement.startPositionRow = pairEndRow;
211
+ valueElement.startPositionColumn = pairEndCol;
212
+ valueElement.startIndex = pairEndIdx;
213
+ valueElement.endPositionRow = pairEndRow;
214
+ valueElement.endPositionColumn = pairEndCol;
215
+ valueElement.endIndex = pairEndIdx;
216
+ }
217
+ }
218
+ const member = new MemberElement();
219
+ if (ctx.sourceMap) {
220
+ member.startPositionRow = pairStartRow;
221
+ member.startPositionColumn = pairStartCol;
222
+ member.startIndex = pairStartIdx;
223
+ member.endPositionRow = pairEndRow;
224
+ member.endPositionColumn = pairEndCol;
225
+ member.endIndex = pairEndIdx;
226
+ }
227
+ member.key = keyElement;
228
+ member.value = valueElement;
229
+ return member;
230
+ },
231
+ walkSequenceItem: (cursor, ctx) => {
232
+ const endRow = cursor.endPosition.row;
233
+ const endCol = cursor.endPosition.column;
234
+ const endIdx = cursor.endIndex;
235
+ let content = null;
236
+ forEachNamedChild(cursor, ctx, child => {
237
+ const {
238
+ nodeType
239
+ } = child;
240
+ if (nodeType === 'tag' || nodeType === 'anchor' || nodeType === 'alias') {
241
+ throw new FallbackNeeded();
242
+ }
243
+ const result = walkFunctions.walkNode(child, ctx);
244
+ if (result !== null) content = result;
245
+ });
246
+ if (content === null) {
247
+ // empty sequence item (just '-' with no value)
248
+ content = ctx.namespace.toElement('');
249
+ content.classes.push('yaml-e-node');
250
+ content.classes.push('yaml-e-scalar');
251
+ if (ctx.sourceMap) {
252
+ content.startPositionRow = endRow;
253
+ content.startPositionColumn = endCol;
254
+ content.startIndex = endIdx;
255
+ content.endPositionRow = endRow;
256
+ content.endPositionColumn = endCol;
257
+ content.endIndex = endIdx;
258
+ }
259
+ }
260
+ return content;
261
+ },
262
+ walkBlockFlowNode: (cursor, ctx) => {
263
+ let content = null;
264
+ forEachNamedChild(cursor, ctx, child => {
265
+ const {
266
+ nodeType
267
+ } = child;
268
+ if (nodeType === 'tag' || nodeType === 'anchor' || nodeType === 'alias') {
269
+ throw new FallbackNeeded();
270
+ }
271
+ if (nodeType === 'comment') return;
272
+ const result = walkFunctions.walkNode(child, ctx);
273
+ if (result !== null && content === null) {
274
+ content = result;
275
+ }
276
+ });
277
+ return content;
278
+ },
279
+ walkPlainScalar: (cursor, ctx) => {
280
+ const formatted = formatFlowPlain(cursor.nodeText);
281
+ const element = ctx.namespace.toElement(resolveScalarContent(formatted));
282
+ if (ctx.sourceMap) setSourceMap(element, cursor);
283
+ if (formatted === '') {
284
+ element.classes.push('yaml-e-node');
285
+ element.classes.push('yaml-e-scalar');
286
+ }
287
+ return element;
288
+ },
289
+ walkSingleQuoteScalar: (cursor, ctx) => {
290
+ const formatted = formatFlowSingleQuoted(cursor.nodeText);
291
+ const element = ctx.namespace.toElement(formatted);
292
+ if (ctx.sourceMap) setSourceMap(element, cursor);
293
+ return element;
294
+ },
295
+ walkDoubleQuoteScalar: (cursor, ctx) => {
296
+ const formatted = formatFlowDoubleQuoted(cursor.nodeText);
297
+ const element = ctx.namespace.toElement(formatted);
298
+ if (ctx.sourceMap) setSourceMap(element, cursor);
299
+ return element;
300
+ },
301
+ walkBlockScalar: (cursor, ctx) => {
302
+ const raw = cursor.nodeText;
303
+ const formatted = raw.trimStart().startsWith('>') ? formatBlockFolded(raw) : formatBlockLiteral(raw);
304
+ const element = ctx.namespace.toElement(formatted);
305
+ if (ctx.sourceMap) setSourceMap(element, cursor);
306
+ return element;
307
+ },
308
+ walkError: (cursor, ctx) => {
309
+ const isUnexpected = !cursor.currentNode.hasError;
310
+ const message = isUnexpected ? '(Unexpected YAML syntax error)' : '(Error YAML syntax error)';
311
+ const ann = new AnnotationElement(message);
312
+ ann.classes.push('error');
313
+ if (ctx.sourceMap) setSourceMap(ann, cursor);
314
+ ctx.annotations.push(ann);
315
+ return null;
316
+ },
317
+ walkNode: (cursor, ctx) => {
318
+ switch (cursor.nodeType) {
319
+ case 'block_mapping':
320
+ case 'flow_mapping':
321
+ return walkFunctions.walkMapping(cursor, ctx);
322
+ case 'block_sequence':
323
+ case 'flow_sequence':
324
+ return walkFunctions.walkSequence(cursor, ctx);
325
+ case 'block_mapping_pair':
326
+ case 'flow_pair':
327
+ return walkFunctions.walkPair(cursor, ctx);
328
+ case 'block_sequence_item':
329
+ return walkFunctions.walkSequenceItem(cursor, ctx);
330
+ case 'block_node':
331
+ case 'flow_node':
332
+ return walkFunctions.walkBlockFlowNode(cursor, ctx);
333
+ case 'plain_scalar':
334
+ return walkFunctions.walkPlainScalar(cursor, ctx);
335
+ case 'single_quote_scalar':
336
+ return walkFunctions.walkSingleQuoteScalar(cursor, ctx);
337
+ case 'double_quote_scalar':
338
+ return walkFunctions.walkDoubleQuoteScalar(cursor, ctx);
339
+ case 'block_scalar':
340
+ return walkFunctions.walkBlockScalar(cursor, ctx);
341
+ case 'tag':
342
+ case 'anchor':
343
+ case 'alias':
344
+ throw new FallbackNeeded();
345
+ case 'ERROR':
346
+ return walkFunctions.walkError(cursor, ctx);
347
+ default:
348
+ return null;
349
+ }
350
+ }
351
+ };
352
+
353
+ /**
354
+ * Direct cursor-based syntactic analysis.
355
+ * Walks the tree-sitter CST once and builds ApiDOM elements directly,
356
+ * eliminating both the TreeCursorSyntaxNode pre-materialization and the
357
+ * intermediate YAML AST passes used by the indirect analysis.
358
+ *
359
+ * Throws FallbackNeeded when the document uses YAML tags, anchors, or aliases,
360
+ * which require the full two-pass indirect analysis to resolve correctly.
361
+ * @public
362
+ */
363
+ const analyze = (cst, {
364
+ sourceMap = false
365
+ } = {}) => {
366
+ const cursor = cst.walk();
367
+ const ctx = {
368
+ sourceMap,
369
+ namespace: createNamespace(),
370
+ annotations: [],
371
+ documentCount: 0
372
+ };
373
+
374
+ // When tree-sitter can't parse the input at all, the root node is ERROR rather than stream.
375
+ // In that case return an empty ParseResultElement containing only the error annotation.
376
+ if (cursor.nodeType !== 'stream') {
377
+ const parseResult = new ParseResultElement();
378
+ if (ctx.sourceMap) setSourceMap(parseResult, cursor);
379
+ walkFunctions.walkError(cursor, ctx);
380
+ ctx.annotations.forEach(ann => parseResult.push(ann));
381
+ return parseResult;
382
+ }
383
+ return walkFunctions.walkStream(cursor, ctx);
384
+ };
385
+ export default analyze;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
+ var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard").default;
5
+ exports.__esModule = true;
6
+ exports.default = void 0;
7
+ var _index = _interopRequireWildcard(require("./direct/index.cjs"));
8
+ var _index2 = _interopRequireDefault(require("./indirect/index.cjs"));
9
+ /**
10
+ * Syntactic analysis dispatcher.
11
+ * Attempts the fast direct cursor-based analysis first.
12
+ * Falls back to the indirect two-pass analysis when the document uses
13
+ * YAML features (tags, anchors, aliases) that the direct path cannot handle.
14
+ * @public
15
+ */
16
+ const analyze = (cst, options = {}) => {
17
+ try {
18
+ return (0, _index.default)(cst, options);
19
+ } catch (e) {
20
+ if (e instanceof _index.FallbackNeeded) {
21
+ return (0, _index2.default)(cst, options);
22
+ }
23
+ throw e;
24
+ }
25
+ };
26
+ var _default = exports.default = analyze;
@@ -0,0 +1,20 @@
1
+ import directAnalyze, { FallbackNeeded } from "./direct/index.mjs";
2
+ import indirectAnalyze from "./indirect/index.mjs";
3
+ /**
4
+ * Syntactic analysis dispatcher.
5
+ * Attempts the fast direct cursor-based analysis first.
6
+ * Falls back to the indirect two-pass analysis when the document uses
7
+ * YAML features (tags, anchors, aliases) that the direct path cannot handle.
8
+ * @public
9
+ */
10
+ const analyze = (cst, options = {}) => {
11
+ try {
12
+ return directAnalyze(cst, options);
13
+ } catch (e) {
14
+ if (e instanceof FallbackNeeded) {
15
+ return indirectAnalyze(cst, options);
16
+ }
17
+ throw e;
18
+ }
19
+ };
20
+ export default analyze;
@@ -2,7 +2,7 @@ import { MediaTypes } from '@swagger-api/apidom-core';
2
2
  import { Namespace } from '@swagger-api/apidom-core';
3
3
  import { ParseResultElement } from '@swagger-api/apidom-core';
4
4
  import { Tree as Tree_2 } from 'web-tree-sitter';
5
- import { Tree as Tree_3 } from 'tree-sitter';
5
+ import type { Tree as Tree_3 } from 'tree-sitter';
6
6
 
7
7
  /**
8
8
  * @public
@@ -47,13 +47,14 @@ export declare interface ParseFunctionOptions {
47
47
  }
48
48
 
49
49
  /**
50
- * This version of syntactic analysis does following transformations:
51
- * `TreeSitter CST -> YAML AST -> ApiDOM`
52
- * Two traversals passes are needed to get from CST to ApiDOM.
50
+ * Syntactic analysis dispatcher.
51
+ * Attempts the fast direct cursor-based analysis first.
52
+ * Falls back to the indirect two-pass analysis when the document uses
53
+ * YAML features (tags, anchors, aliases) that the direct path cannot handle.
53
54
  * @public
54
55
  */
55
- export declare const syntacticAnalysis: (cst: Tree, { sourceMap }?: {
56
- sourceMap?: boolean | undefined;
56
+ export declare const syntacticAnalysis: (cst: Tree, options?: {
57
+ sourceMap?: boolean;
57
58
  }) => ParseResultElement;
58
59
 
59
60
  /**