@speclynx/apidom-parser-adapter-json 1.12.1
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.
- package/CHANGELOG.md +91 -0
- package/LICENSE +202 -0
- package/LICENSES/AFL-3.0.txt +182 -0
- package/LICENSES/Apache-2.0.txt +202 -0
- package/LICENSES/BSD-3-Clause.txt +26 -0
- package/LICENSES/MIT.txt +9 -0
- package/NOTICE +65 -0
- package/README.md +124 -0
- package/dist/167.apidom-parser-adapter-json.browser.js +10 -0
- package/dist/167.apidom-parser-adapter-json.browser.min.js +1 -0
- package/dist/451.apidom-parser-adapter-json.browser.js +10 -0
- package/dist/451.apidom-parser-adapter-json.browser.min.js +1 -0
- package/dist/9786785aaddf11f37840.wasm +0 -0
- package/dist/apidom-parser-adapter-json.browser.js +17850 -0
- package/dist/apidom-parser-adapter-json.browser.min.js +1 -0
- package/package.json +69 -0
- package/src/adapter.cjs +75 -0
- package/src/adapter.mjs +65 -0
- package/src/lexical-analysis/index.cjs +42 -0
- package/src/lexical-analysis/index.mjs +38 -0
- package/src/media-types.cjs +20 -0
- package/src/media-types.mjs +16 -0
- package/src/syntactic-analysis/TreeCursorIterator.cjs +62 -0
- package/src/syntactic-analysis/TreeCursorIterator.mjs +57 -0
- package/src/syntactic-analysis/TreeCursorSyntaxNode.cjs +51 -0
- package/src/syntactic-analysis/TreeCursorSyntaxNode.mjs +47 -0
- package/src/syntactic-analysis/direct/index.cjs +64 -0
- package/src/syntactic-analysis/direct/index.mjs +59 -0
- package/src/syntactic-analysis/direct/visitors/CstVisitor.cjs +163 -0
- package/src/syntactic-analysis/direct/visitors/CstVisitor.mjs +158 -0
- package/src/syntactic-analysis/indirect/index.cjs +56 -0
- package/src/syntactic-analysis/indirect/index.mjs +49 -0
- package/src/syntactic-analysis/indirect/visitors/CstVisitor.cjs +177 -0
- package/src/syntactic-analysis/indirect/visitors/CstVisitor.mjs +172 -0
- package/src/syntactic-analysis/indirect/visitors/JsonAstVisitor.cjs +189 -0
- package/src/syntactic-analysis/indirect/visitors/JsonAstVisitor.mjs +183 -0
- package/types/apidom-parser-adapter-json.d.ts +103 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { JsonArray, JsonDocument, JsonObject, JsonProperty, ParseResult, Error, isNode as isCSTNode, getNodeType as getCSTNodeType } from '@speclynx/apidom-ast';
|
|
2
|
+
import { ParseResultElement, ObjectElement, SourceMapElement, MemberElement, ArrayElement, BooleanElement, NullElement, NumberElement, StringElement, AnnotationElement, isParseResultElement, isPrimitiveElement, isElement, keyMap as keyMapApiDOM, getNodeType as getNodeTypeApiDOM } from '@speclynx/apidom-core';
|
|
3
|
+
export const keyMap = {
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
[ParseResult.type]: ['children'],
|
|
6
|
+
// @ts-ignore
|
|
7
|
+
[JsonDocument.type]: ['children'],
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
[JsonObject.type]: ['children'],
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
[JsonProperty.type]: ['children'],
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
[JsonArray.type]: ['children'],
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
[Error.type]: ['children'],
|
|
16
|
+
...keyMapApiDOM
|
|
17
|
+
};
|
|
18
|
+
export const getNodeType = node => {
|
|
19
|
+
if (isParseResultElement(node)) {
|
|
20
|
+
return 'ParseResultElement';
|
|
21
|
+
}
|
|
22
|
+
if (isElement(node)) {
|
|
23
|
+
return getNodeTypeApiDOM(node);
|
|
24
|
+
}
|
|
25
|
+
return getCSTNodeType(node);
|
|
26
|
+
};
|
|
27
|
+
export const isNode = element => isElement(element) || isCSTNode(element);
|
|
28
|
+
class JsonAstVisitor {
|
|
29
|
+
sourceMap = false;
|
|
30
|
+
annotations;
|
|
31
|
+
ParseResultElement = {
|
|
32
|
+
leave: element => {
|
|
33
|
+
// mark first-non Annotation element as result
|
|
34
|
+
// @ts-ignore
|
|
35
|
+
const elements = element.findElements(isPrimitiveElement);
|
|
36
|
+
if (elements.length > 0) {
|
|
37
|
+
const resultElement = elements[0];
|
|
38
|
+
resultElement.classes.push('result');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// provide annotations
|
|
42
|
+
this.annotations.forEach(annotationElement => {
|
|
43
|
+
element.push(annotationElement);
|
|
44
|
+
});
|
|
45
|
+
this.annotations = [];
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
constructor() {
|
|
49
|
+
this.annotations = [];
|
|
50
|
+
}
|
|
51
|
+
document(node) {
|
|
52
|
+
const element = new ParseResultElement();
|
|
53
|
+
// @ts-ignore
|
|
54
|
+
element._content = node.children;
|
|
55
|
+
return element;
|
|
56
|
+
}
|
|
57
|
+
object(node) {
|
|
58
|
+
const element = new ObjectElement();
|
|
59
|
+
// @ts-ignore
|
|
60
|
+
element._content = node.children;
|
|
61
|
+
this.maybeAddSourceMap(node, element);
|
|
62
|
+
return element;
|
|
63
|
+
}
|
|
64
|
+
property(node) {
|
|
65
|
+
const element = new MemberElement();
|
|
66
|
+
|
|
67
|
+
// @ts-ignore
|
|
68
|
+
element.content.key = node.key;
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
element.content.value = node.value;
|
|
71
|
+
this.maybeAddSourceMap(node, element);
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Process possible errors here that may be present in pair node children as we're using direct field access.
|
|
75
|
+
* There are usually 3 children here found: "key", ":", "value".
|
|
76
|
+
*/
|
|
77
|
+
if (node.children.length > 3) {
|
|
78
|
+
node.children
|
|
79
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
80
|
+
.filter(child => child.type === 'error')
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
82
|
+
.forEach(errorNode => {
|
|
83
|
+
this.error(errorNode, node, [], [node]);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return element;
|
|
87
|
+
}
|
|
88
|
+
key(node) {
|
|
89
|
+
const {
|
|
90
|
+
value,
|
|
91
|
+
parseError
|
|
92
|
+
} = node;
|
|
93
|
+
const element = new StringElement(value);
|
|
94
|
+
if (parseError instanceof Error) {
|
|
95
|
+
element.setMetaProperty('jsonParse', {
|
|
96
|
+
isError: true,
|
|
97
|
+
errorType: parseError.name,
|
|
98
|
+
errorMessage: parseError.message
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
this.maybeAddSourceMap(node, element);
|
|
102
|
+
return element;
|
|
103
|
+
}
|
|
104
|
+
array(node) {
|
|
105
|
+
const element = new ArrayElement();
|
|
106
|
+
// @ts-ignore
|
|
107
|
+
element._content = node.children;
|
|
108
|
+
this.maybeAddSourceMap(node, element);
|
|
109
|
+
return element;
|
|
110
|
+
}
|
|
111
|
+
string(node) {
|
|
112
|
+
const {
|
|
113
|
+
value,
|
|
114
|
+
parseError
|
|
115
|
+
} = node;
|
|
116
|
+
const element = new StringElement(value);
|
|
117
|
+
if (parseError instanceof Error) {
|
|
118
|
+
element.setMetaProperty('jsonParse', {
|
|
119
|
+
isError: true,
|
|
120
|
+
errorType: parseError.name,
|
|
121
|
+
errorMessage: parseError.message
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
this.maybeAddSourceMap(node, element);
|
|
125
|
+
return element;
|
|
126
|
+
}
|
|
127
|
+
number(node) {
|
|
128
|
+
const element = new NumberElement(Number(node.value));
|
|
129
|
+
this.maybeAddSourceMap(node, element);
|
|
130
|
+
return element;
|
|
131
|
+
}
|
|
132
|
+
null(node) {
|
|
133
|
+
const element = new NullElement();
|
|
134
|
+
this.maybeAddSourceMap(node, element);
|
|
135
|
+
return element;
|
|
136
|
+
}
|
|
137
|
+
true(node) {
|
|
138
|
+
const element = new BooleanElement(true);
|
|
139
|
+
this.maybeAddSourceMap(node, element);
|
|
140
|
+
return element;
|
|
141
|
+
}
|
|
142
|
+
false(node) {
|
|
143
|
+
const element = new BooleanElement(false);
|
|
144
|
+
this.maybeAddSourceMap(node, element);
|
|
145
|
+
return element;
|
|
146
|
+
}
|
|
147
|
+
literal(node) {
|
|
148
|
+
if (node.isMissing) {
|
|
149
|
+
const message = `(Missing ${node.value})`;
|
|
150
|
+
const element = new AnnotationElement(message);
|
|
151
|
+
element.classes.push('warning');
|
|
152
|
+
this.maybeAddSourceMap(node, element);
|
|
153
|
+
this.annotations.push(element);
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
error(node, key, parent, path) {
|
|
158
|
+
const message = node.isUnexpected ? `(Unexpected ${node.value})` : `(Error ${node.value})`;
|
|
159
|
+
const element = new AnnotationElement(message);
|
|
160
|
+
element.classes.push('error');
|
|
161
|
+
this.maybeAddSourceMap(node, element);
|
|
162
|
+
if (path.length === 0) {
|
|
163
|
+
// no document to visit, only error is present in CST
|
|
164
|
+
const parseResultElement = new ParseResultElement();
|
|
165
|
+
parseResultElement.push(element);
|
|
166
|
+
return parseResultElement;
|
|
167
|
+
}
|
|
168
|
+
this.annotations.push(element);
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
maybeAddSourceMap(node, element) {
|
|
172
|
+
if (!this.sourceMap) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const sourceMap = new SourceMapElement();
|
|
176
|
+
// @ts-ignore
|
|
177
|
+
sourceMap.position = node.position;
|
|
178
|
+
// @ts-ignore
|
|
179
|
+
sourceMap.astNode = node;
|
|
180
|
+
element.meta.set('sourceMap', sourceMap);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
export default JsonAstVisitor;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { MediaTypes } from '@speclynx/apidom-core';
|
|
2
|
+
import { Namespace } from '@speclynx/apidom-core';
|
|
3
|
+
import { ParseResultElement } from '@speclynx/apidom-core';
|
|
4
|
+
import { Tree } from 'web-tree-sitter';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This version of syntactic analysis translates TreeSitter CTS
|
|
8
|
+
* directly into ApiDOM.
|
|
9
|
+
*
|
|
10
|
+
* Transient transformation of TreeSitter CST is performed
|
|
11
|
+
* using TreeSitter cursor. TreeSitter cursor is a stateful object
|
|
12
|
+
* that allows us to walk syntax tree containing large number of nodes
|
|
13
|
+
* with maximum efficiency. Using this transient CST transformation
|
|
14
|
+
* gives us double the performance when syntactically analyzing
|
|
15
|
+
* CST into ApiDOM.
|
|
16
|
+
*
|
|
17
|
+
* Single traversal pass is needed to get from CST to ApiDOM.
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
declare const analyze: (cst: Tree, { sourceMap }?: {
|
|
21
|
+
sourceMap?: boolean | undefined;
|
|
22
|
+
}) => ParseResultElement;
|
|
23
|
+
export { analyze as syntacticAnalysis }
|
|
24
|
+
export { analyze as syntacticAnalysisDirect }
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
export declare const detect: (source: string) => Promise<boolean>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
34
|
+
export declare const detectionRegExp: RegExp;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
export declare class JSONMediaTypes extends MediaTypes<string> {
|
|
40
|
+
latest(): string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Lexical Analysis of source string using WebTreeSitter.
|
|
45
|
+
* This is WebAssembly version of TreeSitters Lexical Analysis.
|
|
46
|
+
*
|
|
47
|
+
* Given JavaScript doesn't support true parallelism, this
|
|
48
|
+
* code should be as lazy as possible and temporal safety should be fine.
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
export declare const lexicalAnalysis: (source: string) => Promise<Tree>;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
export declare const mediaTypes: JSONMediaTypes;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
61
|
+
export declare const namespace: Namespace;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
export declare const parse: ParseFunction;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @public
|
|
70
|
+
*/
|
|
71
|
+
export declare type ParseFunction = (source: string, options?: ParseFunctionOptions) => Promise<ParseResultElement>;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
export declare interface ParseFunctionOptions {
|
|
77
|
+
sourceMap?: boolean;
|
|
78
|
+
syntacticAnalysis?: 'direct' | 'indirect';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* This version of syntactic analysis does following transformations:
|
|
83
|
+
* `TreeSitter CST -> JSON AST -> ApiDOM`
|
|
84
|
+
*
|
|
85
|
+
* Transient transformation of TreeSitter CST is performed
|
|
86
|
+
* using TreeSitter cursor. TreeSitter cursor is a stateful object
|
|
87
|
+
* that allows us to walk syntax tree containing large number of nodes
|
|
88
|
+
* with maximum efficiency. Using this transient CST transformation
|
|
89
|
+
* gives us double the performance when syntactically analyzing
|
|
90
|
+
* CST into JSON AST.
|
|
91
|
+
*
|
|
92
|
+
* Two traversals passes are needed to get from CST to ApiDOM.
|
|
93
|
+
* This analysis is much slower than the direct one, but allows
|
|
94
|
+
* to do additional analysis magic on JSON AST.
|
|
95
|
+
* @public
|
|
96
|
+
*/
|
|
97
|
+
export declare const syntacticAnalysisIndirect: (cst: Tree, { sourceMap }?: {
|
|
98
|
+
sourceMap?: boolean | undefined;
|
|
99
|
+
}) => ParseResultElement;
|
|
100
|
+
|
|
101
|
+
export { Tree }
|
|
102
|
+
|
|
103
|
+
export { }
|