@sap-ux/cds-annotation-parser 0.1.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/LICENSE +201 -0
- package/README.md +74 -0
- package/dist/constants.d.ts +6 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +10 -0
- package/dist/constants.js.map +1 -0
- package/dist/find-annotation-node.d.ts +40 -0
- package/dist/find-annotation-node.d.ts.map +1 -0
- package/dist/find-annotation-node.js +135 -0
- package/dist/find-annotation-node.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/factory.d.ts +6 -0
- package/dist/parser/factory.d.ts.map +1 -0
- package/dist/parser/factory.js +13 -0
- package/dist/parser/factory.js.map +1 -0
- package/dist/parser/index.d.ts +11 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +17 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/parser.d.ts +242 -0
- package/dist/parser/parser.d.ts.map +1 -0
- package/dist/parser/parser.js +385 -0
- package/dist/parser/parser.js.map +1 -0
- package/dist/parser/tokens.d.ts +103 -0
- package/dist/parser/tokens.d.ts.map +1 -0
- package/dist/parser/tokens.js +287 -0
- package/dist/parser/tokens.js.map +1 -0
- package/dist/transformer/annotation-ast-nodes.d.ts +178 -0
- package/dist/transformer/annotation-ast-nodes.d.ts.map +1 -0
- package/dist/transformer/annotation-ast-nodes.js +69 -0
- package/dist/transformer/annotation-ast-nodes.js.map +1 -0
- package/dist/transformer/ast.d.ts +6 -0
- package/dist/transformer/ast.d.ts.map +1 -0
- package/dist/transformer/ast.js +1227 -0
- package/dist/transformer/ast.js.map +1 -0
- package/dist/transformer/expressions.d.ts +87 -0
- package/dist/transformer/expressions.d.ts.map +1 -0
- package/dist/transformer/expressions.js +548 -0
- package/dist/transformer/expressions.js.map +1 -0
- package/dist/transformer/index.d.ts +5 -0
- package/dist/transformer/index.d.ts.map +1 -0
- package/dist/transformer/index.js +42 -0
- package/dist/transformer/index.js.map +1 -0
- package/dist/transformer/range.d.ts +20 -0
- package/dist/transformer/range.d.ts.map +1 -0
- package/dist/transformer/range.js +31 -0
- package/dist/transformer/range.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +17 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +38 -0
|
@@ -0,0 +1,1227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildAst = exports.locationToRange = void 0;
|
|
4
|
+
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
|
5
|
+
const annotation_ast_nodes_1 = require("./annotation-ast-nodes");
|
|
6
|
+
const factory_1 = require("../parser/factory");
|
|
7
|
+
const expressions_1 = require("./expressions");
|
|
8
|
+
const odata_vocabularies_1 = require("@sap-ux/odata-vocabularies");
|
|
9
|
+
const tokens_1 = require("../parser/tokens");
|
|
10
|
+
const range_1 = require("./range");
|
|
11
|
+
const utils_1 = require("../utils");
|
|
12
|
+
/**
|
|
13
|
+
* Extracts qualifier part from term and adapt range and value for term.
|
|
14
|
+
*
|
|
15
|
+
* @param term Term node
|
|
16
|
+
* @returns Qualifier node
|
|
17
|
+
*/
|
|
18
|
+
const createQualifier = (term) => {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
const segment = term.segments.find((item) => item.value.includes('#'));
|
|
21
|
+
let qRange;
|
|
22
|
+
let qualifierValue = '';
|
|
23
|
+
if ((0, utils_1.isDefined)(segment)) {
|
|
24
|
+
const tokens = segment.value.split('#');
|
|
25
|
+
segment.value = (_a = tokens.shift()) !== null && _a !== void 0 ? _a : '';
|
|
26
|
+
qualifierValue = (_b = tokens.pop()) !== null && _b !== void 0 ? _b : '';
|
|
27
|
+
const len = qualifierValue.length;
|
|
28
|
+
if (segment.range) {
|
|
29
|
+
qRange = {
|
|
30
|
+
start: Object.assign(Object.assign({}, segment.range.end), { character: segment.range.end.character - len }),
|
|
31
|
+
end: Object.assign({}, segment.range.end)
|
|
32
|
+
};
|
|
33
|
+
segment.range.end.character = segment.range.end.character - len - 1;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
type: annotation_ast_nodes_1.QUALIFIER_TYPE,
|
|
38
|
+
value: qualifierValue,
|
|
39
|
+
range: qRange
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
const compareTokensByPosition = (a, b) => {
|
|
43
|
+
return a.startOffset - b.startOffset;
|
|
44
|
+
};
|
|
45
|
+
const adjustPosition = (position, offset) => vscode_languageserver_types_1.Position.create(position.line + offset.line, position.line === 0 ? position.character + offset.character : position.character);
|
|
46
|
+
const locationToRange = (location) => {
|
|
47
|
+
var _a, _b, _c;
|
|
48
|
+
return location
|
|
49
|
+
? vscode_languageserver_types_1.Range.create(location.startLine - 1, ((_a = location.startColumn) !== null && _a !== void 0 ? _a : 0) - 1, ((_b = location.endLine) !== null && _b !== void 0 ? _b : 0) - 1, (_c = location.endColumn) !== null && _c !== void 0 ? _c : 0)
|
|
50
|
+
: undefined;
|
|
51
|
+
};
|
|
52
|
+
exports.locationToRange = locationToRange;
|
|
53
|
+
const existsAndNotRecovered = (nodes) => { var _a; return (0, utils_1.hasItems)(nodes) && !((_a = nodes[0]) === null || _a === void 0 ? void 0 : _a.isInsertedInRecovery); };
|
|
54
|
+
const vocabularyService = new odata_vocabularies_1.VocabularyService(true);
|
|
55
|
+
const vocabularyAliases = [...vocabularyService.getVocabularies().values()].map((vocabulary) => vocabulary.defaultAlias);
|
|
56
|
+
const supportedVocabularyAliases = new Set([...vocabularyAliases, ...vocabularyService.cdsVocabulary.groupNames]);
|
|
57
|
+
const findNextToken = (tokens, previousTokenEndOffset) => {
|
|
58
|
+
const prevTokenIdx = tokens.findIndex((token) => token.endOffset === previousTokenEndOffset);
|
|
59
|
+
return tokens[prevTokenIdx + 1];
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
*
|
|
63
|
+
*/
|
|
64
|
+
class CstToAstVisitor extends factory_1.Visitor {
|
|
65
|
+
constructor() {
|
|
66
|
+
super(...arguments);
|
|
67
|
+
this.tokenVector = [];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Main visitor entry.
|
|
71
|
+
*
|
|
72
|
+
* @param cstNode CST node
|
|
73
|
+
* @returns Result of the visitor call for the given cstNode
|
|
74
|
+
*/
|
|
75
|
+
visit(cstNode) {
|
|
76
|
+
return super.visit(cstNode, cstNode.location);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Converts cst node location to range object.
|
|
80
|
+
*
|
|
81
|
+
* @param location CST node location
|
|
82
|
+
* @returns Range object
|
|
83
|
+
*/
|
|
84
|
+
locationToRange(location) {
|
|
85
|
+
const range = (0, exports.locationToRange)(location);
|
|
86
|
+
if (this.startPosition && range) {
|
|
87
|
+
return vscode_languageserver_types_1.Range.create(adjustPosition(range.start, this.startPosition), adjustPosition(range.end, this.startPosition));
|
|
88
|
+
}
|
|
89
|
+
return range;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Converts given token to range object.
|
|
93
|
+
*
|
|
94
|
+
* @param token Token to convert
|
|
95
|
+
* @returns Range object
|
|
96
|
+
*/
|
|
97
|
+
tokenToRange(token) {
|
|
98
|
+
var _a, _b, _c, _d, _e, _f;
|
|
99
|
+
const start = vscode_languageserver_types_1.Position.create(((_a = token.startLine) !== null && _a !== void 0 ? _a : 0) - 1, ((_b = token.startColumn) !== null && _b !== void 0 ? _b : 0) - 1);
|
|
100
|
+
const line = (0, utils_1.hasNaNOrUndefined)(token.endLine) ? ((_c = token.startLine) !== null && _c !== void 0 ? _c : 0) - 1 : ((_d = token.endLine) !== null && _d !== void 0 ? _d : 0) - 1;
|
|
101
|
+
const char = (0, utils_1.hasNaNOrUndefined)(token.endColumn)
|
|
102
|
+
? ((_e = token.startColumn) !== null && _e !== void 0 ? _e : 0) - 1 + token.image.length
|
|
103
|
+
: (_f = token.endColumn) !== null && _f !== void 0 ? _f : 0;
|
|
104
|
+
const end = vscode_languageserver_types_1.Position.create(line, char);
|
|
105
|
+
if (this.startPosition) {
|
|
106
|
+
return vscode_languageserver_types_1.Range.create(adjustPosition(start, this.startPosition), adjustPosition(end, this.startPosition));
|
|
107
|
+
}
|
|
108
|
+
return vscode_languageserver_types_1.Range.create(start, end);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Converts CST token to AST token.
|
|
112
|
+
*
|
|
113
|
+
* @param token CST token
|
|
114
|
+
* @returns AST token
|
|
115
|
+
*/
|
|
116
|
+
createToken(token) {
|
|
117
|
+
return {
|
|
118
|
+
type: annotation_ast_nodes_1.TOKEN_TYPE,
|
|
119
|
+
value: token.image,
|
|
120
|
+
range: this.tokenToRange(token)
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Extracts qouted literal from the given cst token.
|
|
125
|
+
*
|
|
126
|
+
* @param context CST token
|
|
127
|
+
* @returns String literal (without quotes)
|
|
128
|
+
*/
|
|
129
|
+
getQuotedLiteralValue(context) {
|
|
130
|
+
return context.image.split("'")[1];
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Converts the given CST token to a path.
|
|
134
|
+
*
|
|
135
|
+
* @param identifier CST token
|
|
136
|
+
* @returns Path object
|
|
137
|
+
*/
|
|
138
|
+
pathFromIdentifier(identifier) {
|
|
139
|
+
return {
|
|
140
|
+
type: annotation_ast_nodes_1.PATH_TYPE,
|
|
141
|
+
value: identifier.image,
|
|
142
|
+
segments: [
|
|
143
|
+
{
|
|
144
|
+
type: annotation_ast_nodes_1.IDENTIFIER_TYPE,
|
|
145
|
+
value: identifier.image,
|
|
146
|
+
range: this.tokenToRange(identifier)
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
separators: [],
|
|
150
|
+
range: this.tokenToRange(identifier)
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Converts given CST tokens to ast tokens. Used to convert comma tokens.
|
|
155
|
+
*
|
|
156
|
+
* @param parma Array of CST tokens
|
|
157
|
+
* @returns Array of AST tokens
|
|
158
|
+
*/
|
|
159
|
+
getCommaToken(parma = []) {
|
|
160
|
+
return parma.map((item) => ({
|
|
161
|
+
type: annotation_ast_nodes_1.TOKEN_TYPE,
|
|
162
|
+
value: item.image,
|
|
163
|
+
range: this.tokenToRange(item)
|
|
164
|
+
}));
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Extracts qualifier from the given annotation assignment.
|
|
168
|
+
*
|
|
169
|
+
* @param assignment Annotation assignment
|
|
170
|
+
* @returns Qualifier node or undefined if not found
|
|
171
|
+
*/
|
|
172
|
+
getQualifier(assignment) {
|
|
173
|
+
if (!(0, utils_1.hasItems)(assignment.NumberSign)) {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
const range = (0, utils_1.hasItems)(assignment.NumberSign) ? this.tokenToRange(assignment.NumberSign[0]) : undefined;
|
|
177
|
+
if (range) {
|
|
178
|
+
// We need position after # symbol
|
|
179
|
+
range.start.character++;
|
|
180
|
+
range.end.character++;
|
|
181
|
+
}
|
|
182
|
+
const qualifier = {
|
|
183
|
+
type: annotation_ast_nodes_1.QUALIFIER_TYPE,
|
|
184
|
+
value: '',
|
|
185
|
+
range: range
|
|
186
|
+
};
|
|
187
|
+
if ((0, utils_1.hasItems)(assignment.Identifier)) {
|
|
188
|
+
if (qualifier.range) {
|
|
189
|
+
qualifier.range.end = this.tokenToRange(assignment.Identifier[0]).end;
|
|
190
|
+
}
|
|
191
|
+
qualifier.value = assignment.Identifier[0].image;
|
|
192
|
+
}
|
|
193
|
+
return qualifier;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Converts given assignment to top level annotation group ast node.
|
|
197
|
+
*
|
|
198
|
+
* @param path First segment of the path is used as group name
|
|
199
|
+
* @param assignment Annotation assignment
|
|
200
|
+
* @param location cst location
|
|
201
|
+
* @returns Annotation group object
|
|
202
|
+
*/
|
|
203
|
+
toTopLevelAnnotationPathGroup(path, assignment, location) {
|
|
204
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
205
|
+
const items = ((_c = (_b = (_a = assignment.children.value) === null || _a === void 0 ? void 0 : _a[0].children.struct) === null || _b === void 0 ? void 0 : _b[0].children.assignment) !== null && _c !== void 0 ? _c : []).map((childAssignment, index, childAssignments) => {
|
|
206
|
+
var _a, _b, _c, _d;
|
|
207
|
+
const annotation = this.visit(childAssignment);
|
|
208
|
+
// check for specific situation where current child has no value and separating comma to next child is missing
|
|
209
|
+
// then: current child value is represented by a path and next child path is empty
|
|
210
|
+
const nextChildAssignment = index < childAssignments.length - 1 ? childAssignments[index + 1] : null;
|
|
211
|
+
if (nextChildAssignment &&
|
|
212
|
+
!nextChildAssignment.children.path &&
|
|
213
|
+
nextChildAssignment.children.Colon &&
|
|
214
|
+
nextChildAssignment.children.value &&
|
|
215
|
+
childAssignment.children.value[0].children.path) {
|
|
216
|
+
// current child has no value (separating comma to next child is missing)
|
|
217
|
+
const start = this.tokenToRange(childAssignment.children.Colon[0]).end;
|
|
218
|
+
const end = (_d = (_c = this.locationToRange((_b = (_a = childAssignment.children.value) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.location)) === null || _c === void 0 ? void 0 : _c.start) !== null && _d !== void 0 ? _d : start;
|
|
219
|
+
annotation.value = {
|
|
220
|
+
type: annotation_ast_nodes_1.EMPTY_VALUE_TYPE,
|
|
221
|
+
range: vscode_languageserver_types_1.Range.create(start, end)
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
return annotation;
|
|
225
|
+
});
|
|
226
|
+
const commas = this.getCommaToken((_f = (_e = (_d = assignment.children.value) === null || _d === void 0 ? void 0 : _d[0].children) === null || _e === void 0 ? void 0 : _e.struct) === null || _f === void 0 ? void 0 : _f[0].children.Comma);
|
|
227
|
+
const ast = {
|
|
228
|
+
type: annotation_ast_nodes_1.ANNOTATION_GROUP_TYPE,
|
|
229
|
+
name: path.segments[0],
|
|
230
|
+
items: {
|
|
231
|
+
type: annotation_ast_nodes_1.ANNOTATION_GROUP_ITEMS_TYPE,
|
|
232
|
+
items,
|
|
233
|
+
range: this.locationToRange((_h = (_g = assignment.children.value) === null || _g === void 0 ? void 0 : _g[0]) === null || _h === void 0 ? void 0 : _h.location),
|
|
234
|
+
commas
|
|
235
|
+
},
|
|
236
|
+
range: this.locationToRange(location)
|
|
237
|
+
};
|
|
238
|
+
if ((_j = assignment.children.Colon) === null || _j === void 0 ? void 0 : _j.length) {
|
|
239
|
+
ast.colon = {
|
|
240
|
+
type: annotation_ast_nodes_1.TOKEN_TYPE,
|
|
241
|
+
value: assignment.children.Colon[0].image,
|
|
242
|
+
range: this.tokenToRange(assignment.children.Colon[0])
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
if ((_l = (_k = assignment.children.value) === null || _k === void 0 ? void 0 : _k[0]) === null || _l === void 0 ? void 0 : _l.children.struct) {
|
|
246
|
+
const struct = assignment.children.value[0].children.struct[0];
|
|
247
|
+
if (existsAndNotRecovered(struct.children.LCurly)) {
|
|
248
|
+
ast.items.openToken = this.createToken(struct.children.LCurly[0]);
|
|
249
|
+
}
|
|
250
|
+
if (existsAndNotRecovered(struct.children.RCurly)) {
|
|
251
|
+
ast.items.closeToken = this.createToken(struct.children.RCurly[0]);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return ast;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Creates colon token from the given assignment.
|
|
258
|
+
*
|
|
259
|
+
* @param assignment Assignment CST node
|
|
260
|
+
* @returns Colon ast token or undefined if not found
|
|
261
|
+
*/
|
|
262
|
+
getColon(assignment) {
|
|
263
|
+
var _a;
|
|
264
|
+
if ((_a = assignment.children.Colon) === null || _a === void 0 ? void 0 : _a.length) {
|
|
265
|
+
return {
|
|
266
|
+
type: annotation_ast_nodes_1.TOKEN_TYPE,
|
|
267
|
+
range: this.tokenToRange(assignment.children.Colon[0]),
|
|
268
|
+
value: assignment.children.Colon[0].image
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Converts given assignment to top level annotation path or annotation group path node.
|
|
275
|
+
*
|
|
276
|
+
* @param assignment Assignment to convert
|
|
277
|
+
* @param location CST location
|
|
278
|
+
* @returns Annotation or annotation group path node
|
|
279
|
+
*/
|
|
280
|
+
toTopLevelAnnotationPath(assignment, location) {
|
|
281
|
+
const path = this.visit(assignment.children.path[0]);
|
|
282
|
+
if (path.segments.length !== 1 || (path.segments.length === 1 && !supportedVocabularyAliases.has(path.value))) {
|
|
283
|
+
const ast = {
|
|
284
|
+
type: annotation_ast_nodes_1.ANNOTATION_TYPE,
|
|
285
|
+
term: path,
|
|
286
|
+
range: this.locationToRange(location)
|
|
287
|
+
};
|
|
288
|
+
ast.colon = this.getColon(assignment);
|
|
289
|
+
const qualifier = this.getQualifier(assignment.children);
|
|
290
|
+
if (qualifier) {
|
|
291
|
+
ast.qualifier = qualifier;
|
|
292
|
+
}
|
|
293
|
+
// Flattened qualifier syntax handling
|
|
294
|
+
const qSegment = Math.min(supportedVocabularyAliases.has(path.segments[0].value) ? ast.term.segments.length - 1 : 0, 1);
|
|
295
|
+
if (!ast.qualifier && qSegment >= 0 && ast.term.segments[qSegment].value.includes('#')) {
|
|
296
|
+
ast.qualifier = createQualifier(ast.term);
|
|
297
|
+
}
|
|
298
|
+
if ((0, utils_1.hasItems)(assignment.children.value)) {
|
|
299
|
+
ast.value = this.visit(assignment.children.value[0]);
|
|
300
|
+
}
|
|
301
|
+
return ast;
|
|
302
|
+
}
|
|
303
|
+
else if (path.segments.length === 1 && supportedVocabularyAliases.has(path.value)) {
|
|
304
|
+
return this.toTopLevelAnnotationPathGroup(path, assignment, location);
|
|
305
|
+
}
|
|
306
|
+
return undefined;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Converts given assignment to top level annotation node.
|
|
310
|
+
*
|
|
311
|
+
* @param assignment Assignment to convert
|
|
312
|
+
* @param location CST location
|
|
313
|
+
* @returns Annotation ast node
|
|
314
|
+
*/
|
|
315
|
+
toTopLevelAnnotation(assignment, location) {
|
|
316
|
+
var _a;
|
|
317
|
+
if ((0, utils_1.isDefined)(assignment.location) &&
|
|
318
|
+
isNaN(assignment.location.startOffset) &&
|
|
319
|
+
assignment.recoveredNode === true) {
|
|
320
|
+
return undefined;
|
|
321
|
+
}
|
|
322
|
+
if (assignment.children.path) {
|
|
323
|
+
return this.toTopLevelAnnotationPath(assignment, location);
|
|
324
|
+
}
|
|
325
|
+
if (assignment.children.value && assignment.children.Colon && !assignment.children.path) {
|
|
326
|
+
const end = this.tokenToRange(assignment.children.Colon[0]).start;
|
|
327
|
+
const start = (0, utils_1.isDefined)(this.startPosition)
|
|
328
|
+
? { line: this.startPosition.line, character: this.startPosition.character }
|
|
329
|
+
: end;
|
|
330
|
+
const range = {
|
|
331
|
+
start,
|
|
332
|
+
end
|
|
333
|
+
};
|
|
334
|
+
const ast = {
|
|
335
|
+
type: annotation_ast_nodes_1.ANNOTATION_TYPE,
|
|
336
|
+
term: {
|
|
337
|
+
segments: [],
|
|
338
|
+
separators: [],
|
|
339
|
+
type: 'path',
|
|
340
|
+
value: '',
|
|
341
|
+
range
|
|
342
|
+
},
|
|
343
|
+
range: (0, range_1.copyRange)(range)
|
|
344
|
+
};
|
|
345
|
+
if ((_a = assignment.children.Colon) === null || _a === void 0 ? void 0 : _a.length) {
|
|
346
|
+
ast.colon = {
|
|
347
|
+
type: annotation_ast_nodes_1.TOKEN_TYPE,
|
|
348
|
+
range: this.tokenToRange(assignment.children.Colon[0]),
|
|
349
|
+
value: assignment.children.Colon[0].image
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
ast.qualifier = this.getQualifier(assignment.children);
|
|
353
|
+
if ((0, utils_1.hasItems)(assignment.children.value)) {
|
|
354
|
+
ast.value = this.visit(assignment.children.value[0]);
|
|
355
|
+
}
|
|
356
|
+
return ast;
|
|
357
|
+
}
|
|
358
|
+
return undefined;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Creates declaration node.
|
|
362
|
+
*
|
|
363
|
+
* @param context CST decrataion children
|
|
364
|
+
* @param location CST location of the given context
|
|
365
|
+
* @returns Declaration ast node or undefined if no items found in the context
|
|
366
|
+
*/
|
|
367
|
+
declaration(context, location) {
|
|
368
|
+
if ((0, utils_1.hasItems)(context.assignment)) {
|
|
369
|
+
return this.toTopLevelAnnotation(context.assignment[0], location);
|
|
370
|
+
}
|
|
371
|
+
return undefined;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Converts number string image to number value.
|
|
375
|
+
*
|
|
376
|
+
* @param image String image of the number
|
|
377
|
+
* @returns Converted number value or the given image itself if conversion couldn't be done
|
|
378
|
+
*/
|
|
379
|
+
numberValue(image) {
|
|
380
|
+
const num = Number.parseFloat(image || '0'); // not Number.parseInt() !
|
|
381
|
+
if (Number.isSafeInteger(num) || (!Number.isNaN(num) && Number.isFinite(num))) {
|
|
382
|
+
return num;
|
|
383
|
+
}
|
|
384
|
+
return image;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Converts collection value node.
|
|
388
|
+
*
|
|
389
|
+
* @param context CST collection children
|
|
390
|
+
* @param location CST location
|
|
391
|
+
* @returns Collection annotation value node
|
|
392
|
+
*/
|
|
393
|
+
collectionValue(context, location) {
|
|
394
|
+
if (context.extendCollectionValue) {
|
|
395
|
+
return undefined;
|
|
396
|
+
}
|
|
397
|
+
return this.value(context, location);
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Converts string value node.
|
|
401
|
+
*
|
|
402
|
+
* @param context CST value children
|
|
403
|
+
* @returns String or multiline string literal or undefined if no item found
|
|
404
|
+
*/
|
|
405
|
+
stringValue(context) {
|
|
406
|
+
if ((0, utils_1.hasItems)(context.string)) {
|
|
407
|
+
return this.visit(context.string[0]);
|
|
408
|
+
}
|
|
409
|
+
if ((0, utils_1.hasItems)(context.multiLineStringStripIndent)) {
|
|
410
|
+
return this.visit(context.multiLineStringStripIndent[0]);
|
|
411
|
+
}
|
|
412
|
+
if ((0, utils_1.hasItems)(context.multiLineString)) {
|
|
413
|
+
return this.visit(context.multiLineString[0]);
|
|
414
|
+
}
|
|
415
|
+
return undefined;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Value converter subfunction which calls corresponding visitor for child element (if context permits).
|
|
419
|
+
*
|
|
420
|
+
* @param context Value children CST nodes
|
|
421
|
+
* @returns Object with visitor call result and flag indicating that the visitor call took place
|
|
422
|
+
*/
|
|
423
|
+
valueNestedVisitor(context) {
|
|
424
|
+
if ((0, utils_1.hasItems)(context.enum)) {
|
|
425
|
+
return { done: true, result: this.visit(context.enum[0]) };
|
|
426
|
+
}
|
|
427
|
+
if ((0, utils_1.hasItems)(context.struct)) {
|
|
428
|
+
return { done: true, result: this.visit(context.struct[0]) };
|
|
429
|
+
}
|
|
430
|
+
if ((0, utils_1.hasItems)(context.collection)) {
|
|
431
|
+
return { done: true, result: this.visit(context.collection[0]) };
|
|
432
|
+
}
|
|
433
|
+
if ((0, utils_1.hasItems)(context.path)) {
|
|
434
|
+
return { done: true, result: this.visit(context.path[0]) };
|
|
435
|
+
}
|
|
436
|
+
if ((0, utils_1.hasItems)(context.expression)) {
|
|
437
|
+
return { done: true, result: this.visit(context.expression[0]) };
|
|
438
|
+
}
|
|
439
|
+
return { done: false };
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Value converter subfunction which converts primitive value (if context permits).
|
|
443
|
+
*
|
|
444
|
+
* @param context Value children CST nodes
|
|
445
|
+
* @param location CST node location
|
|
446
|
+
* @returns Object with result of the conversion and a flag indicating that the conversion took place
|
|
447
|
+
*/
|
|
448
|
+
primitiveValueConverter(context, location) {
|
|
449
|
+
if ((0, utils_1.hasItems)(context.string) ||
|
|
450
|
+
(0, utils_1.hasItems)(context.multiLineStringStripIndent) ||
|
|
451
|
+
(0, utils_1.hasItems)(context.multiLineString)) {
|
|
452
|
+
return { done: true, result: this.stringValue(context) };
|
|
453
|
+
}
|
|
454
|
+
if ((0, utils_1.hasItems)(context.Number)) {
|
|
455
|
+
return {
|
|
456
|
+
done: true,
|
|
457
|
+
result: {
|
|
458
|
+
type: annotation_ast_nodes_1.NUMBER_LITERAL_TYPE,
|
|
459
|
+
value: this.numberValue(context.Number[0].image),
|
|
460
|
+
range: this.locationToRange(location)
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
if ((0, utils_1.hasItems)(context.False)) {
|
|
465
|
+
return {
|
|
466
|
+
done: true,
|
|
467
|
+
result: {
|
|
468
|
+
type: annotation_ast_nodes_1.BOOLEAN_TYPE,
|
|
469
|
+
value: false,
|
|
470
|
+
range: this.locationToRange(location)
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
if ((0, utils_1.hasItems)(context.True)) {
|
|
475
|
+
return {
|
|
476
|
+
done: true,
|
|
477
|
+
result: {
|
|
478
|
+
type: annotation_ast_nodes_1.BOOLEAN_TYPE,
|
|
479
|
+
value: true,
|
|
480
|
+
range: this.locationToRange(location)
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
if ((0, utils_1.hasItems)(context.Null)) {
|
|
485
|
+
return {
|
|
486
|
+
done: true,
|
|
487
|
+
result: {
|
|
488
|
+
type: annotation_ast_nodes_1.TOKEN_TYPE,
|
|
489
|
+
value: context.Null[0].image.toLowerCase(),
|
|
490
|
+
range: this.locationToRange(location)
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
if ((0, utils_1.hasItems)(context.Binary)) {
|
|
495
|
+
return {
|
|
496
|
+
done: true,
|
|
497
|
+
result: {
|
|
498
|
+
type: annotation_ast_nodes_1.QUOTED_LITERAL_TYPE,
|
|
499
|
+
value: this.getQuotedLiteralValue(context.Binary[0]),
|
|
500
|
+
range: this.locationToRange(location),
|
|
501
|
+
kind: 'binary'
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
if ((0, utils_1.hasItems)(context.Date)) {
|
|
506
|
+
return {
|
|
507
|
+
done: true,
|
|
508
|
+
result: {
|
|
509
|
+
type: annotation_ast_nodes_1.QUOTED_LITERAL_TYPE,
|
|
510
|
+
value: this.getQuotedLiteralValue(context.Date[0]),
|
|
511
|
+
range: this.locationToRange(location),
|
|
512
|
+
kind: 'date'
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
if ((0, utils_1.hasItems)(context.Time)) {
|
|
517
|
+
return {
|
|
518
|
+
done: true,
|
|
519
|
+
result: {
|
|
520
|
+
type: annotation_ast_nodes_1.QUOTED_LITERAL_TYPE,
|
|
521
|
+
value: this.getQuotedLiteralValue(context.Time[0]),
|
|
522
|
+
range: this.locationToRange(location),
|
|
523
|
+
kind: 'time'
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
if ((0, utils_1.hasItems)(context.Timestamp)) {
|
|
528
|
+
return {
|
|
529
|
+
done: true,
|
|
530
|
+
result: {
|
|
531
|
+
type: annotation_ast_nodes_1.QUOTED_LITERAL_TYPE,
|
|
532
|
+
value: this.getQuotedLiteralValue(context.Timestamp[0]),
|
|
533
|
+
range: this.locationToRange(location),
|
|
534
|
+
kind: 'timestamp'
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
return { done: false };
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Converts value children to value ast node.
|
|
542
|
+
*
|
|
543
|
+
* @param context CST value children
|
|
544
|
+
* @param location CST location
|
|
545
|
+
* @returns annotation value ast node or undefined if no items found
|
|
546
|
+
*/
|
|
547
|
+
value(context, location) {
|
|
548
|
+
const nested = this.valueNestedVisitor(context);
|
|
549
|
+
if (nested.done) {
|
|
550
|
+
return nested.result;
|
|
551
|
+
}
|
|
552
|
+
const primitive = this.primitiveValueConverter(context, location);
|
|
553
|
+
if (primitive.done) {
|
|
554
|
+
return primitive.result;
|
|
555
|
+
}
|
|
556
|
+
if (!(0, utils_1.hasNaNOrUndefined)(location.endOffset)) {
|
|
557
|
+
// create empty value
|
|
558
|
+
return {
|
|
559
|
+
type: annotation_ast_nodes_1.EMPTY_VALUE_TYPE,
|
|
560
|
+
range: this.locationToRange(location)
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
return undefined;
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Converts expression children to expression ast node.
|
|
567
|
+
*
|
|
568
|
+
* @param context CST expression children
|
|
569
|
+
* @param location CST location
|
|
570
|
+
* @returns Expression value ast node
|
|
571
|
+
*/
|
|
572
|
+
expression(context, location) {
|
|
573
|
+
var _a, _b;
|
|
574
|
+
/**
|
|
575
|
+
* Builds operator.
|
|
576
|
+
*
|
|
577
|
+
* @param operatorToken Operator CST token
|
|
578
|
+
* @param range Token range
|
|
579
|
+
* @returns Operator node
|
|
580
|
+
*/
|
|
581
|
+
function buildOperator(operatorToken, range) {
|
|
582
|
+
const operator = { type: annotation_ast_nodes_1.OPERATOR_TYPE, value: operatorToken.image, range };
|
|
583
|
+
return operator;
|
|
584
|
+
}
|
|
585
|
+
const openToken = existsAndNotRecovered(context.LParen) ? this.createToken(context.LParen[0]) : undefined;
|
|
586
|
+
const closeToken = existsAndNotRecovered(context.RParen) ? this.createToken(context.RParen[0]) : undefined;
|
|
587
|
+
const range = this.locationToRange(location);
|
|
588
|
+
const operators = ((_a = context.Operator) !== null && _a !== void 0 ? _a : []).map((token) => buildOperator(token, this.tokenToRange(token)));
|
|
589
|
+
const operands = ((_b = context.value) !== null && _b !== void 0 ? _b : []).map((token) => this.visit(token));
|
|
590
|
+
const expression = { operators, operands, openToken, closeToken, range };
|
|
591
|
+
const unsupportedOperator = operators.find((operator) => {
|
|
592
|
+
const operatorNames = expressions_1.operatorImageMap[operator.value.toUpperCase()];
|
|
593
|
+
return operatorNames.length && !operatorNames.some((operatorName) => expressions_1.operatorMap[operatorName].edmName);
|
|
594
|
+
});
|
|
595
|
+
if (unsupportedOperator || !range) {
|
|
596
|
+
const type = annotation_ast_nodes_1.UNSUPPORTED_OPERATOR_EXPRESSION_TYPE;
|
|
597
|
+
return Object.assign(Object.assign({}, expression), { type, unsupportedOperator });
|
|
598
|
+
}
|
|
599
|
+
try {
|
|
600
|
+
const protoExpression = (0, expressions_1.rebuildNumberSigns)({ operators, operands, range });
|
|
601
|
+
const expression = (0, expressions_1.buildExpression)(protoExpression);
|
|
602
|
+
if (range) {
|
|
603
|
+
expression.range = range;
|
|
604
|
+
}
|
|
605
|
+
if (openToken) {
|
|
606
|
+
expression.openToken = openToken;
|
|
607
|
+
}
|
|
608
|
+
if (closeToken) {
|
|
609
|
+
expression.closeToken = closeToken;
|
|
610
|
+
}
|
|
611
|
+
return expression;
|
|
612
|
+
}
|
|
613
|
+
catch (e) {
|
|
614
|
+
// expression did not follow grammar rules - return expression with empty operatorName
|
|
615
|
+
return Object.assign(Object.assign({}, expression), { type: annotation_ast_nodes_1.INCORRECT_EXPRESSION_TYPE, message: e.toString() });
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Converts enum children to enum ast node.
|
|
620
|
+
*
|
|
621
|
+
* @param context CST enum children
|
|
622
|
+
* @param location CST location
|
|
623
|
+
* @returns Enum value ast node
|
|
624
|
+
*/
|
|
625
|
+
enum(context, location) {
|
|
626
|
+
var _a;
|
|
627
|
+
const range = this.locationToRange(location);
|
|
628
|
+
if (range) {
|
|
629
|
+
range.start.character++;
|
|
630
|
+
}
|
|
631
|
+
const path = ((_a = context.path) === null || _a === void 0 ? void 0 : _a.length) === 1
|
|
632
|
+
? this.visit(context.path[0])
|
|
633
|
+
: {
|
|
634
|
+
type: annotation_ast_nodes_1.PATH_TYPE,
|
|
635
|
+
value: '',
|
|
636
|
+
segments: [],
|
|
637
|
+
separators: [],
|
|
638
|
+
range
|
|
639
|
+
};
|
|
640
|
+
return {
|
|
641
|
+
type: annotation_ast_nodes_1.ENUM_TYPE,
|
|
642
|
+
path,
|
|
643
|
+
range: this.locationToRange(location)
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Converts string children to string ast node.
|
|
648
|
+
*
|
|
649
|
+
* @param context CST string children
|
|
650
|
+
* @param location CST location
|
|
651
|
+
* @returns String literal ast node
|
|
652
|
+
*/
|
|
653
|
+
string(context, location) {
|
|
654
|
+
var _a;
|
|
655
|
+
const range = this.locationToRange(location);
|
|
656
|
+
const value = ((_a = context.String) === null || _a === void 0 ? void 0 : _a.length) === 1 ? context.String[0].image : '';
|
|
657
|
+
const ast = {
|
|
658
|
+
type: annotation_ast_nodes_1.STRING_LITERAL_TYPE,
|
|
659
|
+
value,
|
|
660
|
+
range
|
|
661
|
+
};
|
|
662
|
+
if (existsAndNotRecovered(context.SingleQuote)) {
|
|
663
|
+
ast.openToken = this.createToken(context.SingleQuote[0]);
|
|
664
|
+
}
|
|
665
|
+
if (existsAndNotRecovered(context.StringExit)) {
|
|
666
|
+
ast.closeToken = this.createToken(context.StringExit[0]);
|
|
667
|
+
}
|
|
668
|
+
return ast;
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Converts multi line string children to ast node.
|
|
672
|
+
*
|
|
673
|
+
* @param context CST multi line string children
|
|
674
|
+
* @param location CST location
|
|
675
|
+
* @returns Multi line string literal ast node
|
|
676
|
+
*/
|
|
677
|
+
multiLineString(context, location) {
|
|
678
|
+
var _a;
|
|
679
|
+
const range = this.locationToRange(location);
|
|
680
|
+
const value = ((_a = context.MultiLineString) === null || _a === void 0 ? void 0 : _a.length) === 1 ? context.MultiLineString[0].image : '';
|
|
681
|
+
const ast = {
|
|
682
|
+
type: annotation_ast_nodes_1.MULTI_LINE_STRING_LITERAL_TYPE,
|
|
683
|
+
stripIndentation: false,
|
|
684
|
+
value,
|
|
685
|
+
range
|
|
686
|
+
};
|
|
687
|
+
if (existsAndNotRecovered(context.Backtick)) {
|
|
688
|
+
ast.openToken = this.createToken(context.Backtick[0]);
|
|
689
|
+
}
|
|
690
|
+
if (existsAndNotRecovered(context.MultiLineStringExit)) {
|
|
691
|
+
ast.closeToken = this.createToken(context.MultiLineStringExit[0]);
|
|
692
|
+
}
|
|
693
|
+
return ast;
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Converts multi line strip indent children to ast node.
|
|
697
|
+
*
|
|
698
|
+
* @param context CST multi line strip indent children
|
|
699
|
+
* @param location CST location
|
|
700
|
+
* @returns Multi line string literal ast node
|
|
701
|
+
*/
|
|
702
|
+
multiLineStringStripIndent(context, location) {
|
|
703
|
+
var _a;
|
|
704
|
+
const range = this.locationToRange(location);
|
|
705
|
+
const value = ((_a = context.MultiLineString) === null || _a === void 0 ? void 0 : _a.length) === 1 ? context.MultiLineString[0].image : '';
|
|
706
|
+
const ast = {
|
|
707
|
+
type: annotation_ast_nodes_1.MULTI_LINE_STRING_LITERAL_TYPE,
|
|
708
|
+
stripIndentation: true,
|
|
709
|
+
value,
|
|
710
|
+
range
|
|
711
|
+
};
|
|
712
|
+
if (existsAndNotRecovered(context.TripleBacktick)) {
|
|
713
|
+
ast.openToken = this.createToken(context.TripleBacktick[0]);
|
|
714
|
+
}
|
|
715
|
+
if (existsAndNotRecovered(context.MultiLineStringStripIndentExit)) {
|
|
716
|
+
ast.closeToken = this.createToken(context.MultiLineStringStripIndentExit[0]);
|
|
717
|
+
}
|
|
718
|
+
return ast;
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Converts collection children to ast node.
|
|
722
|
+
*
|
|
723
|
+
* @param context CST collection children
|
|
724
|
+
* @param location CST location
|
|
725
|
+
* @returns Collection ast node
|
|
726
|
+
*/
|
|
727
|
+
collection(context, location) {
|
|
728
|
+
const range = this.locationToRange(location);
|
|
729
|
+
const commas = this.getCommaToken(context === null || context === void 0 ? void 0 : context.Comma);
|
|
730
|
+
const ast = {
|
|
731
|
+
type: annotation_ast_nodes_1.COLLECTION_TYPE,
|
|
732
|
+
items: (0, utils_1.hasItems)(context.collectionValue)
|
|
733
|
+
? context.collectionValue
|
|
734
|
+
.map((value) => this.visit(value))
|
|
735
|
+
.filter((item) => item !== undefined)
|
|
736
|
+
: [],
|
|
737
|
+
range,
|
|
738
|
+
commas
|
|
739
|
+
};
|
|
740
|
+
if (existsAndNotRecovered(context.LBracket)) {
|
|
741
|
+
ast.openToken = this.createToken(context.LBracket[0]);
|
|
742
|
+
}
|
|
743
|
+
if (existsAndNotRecovered(context.RBracket)) {
|
|
744
|
+
ast.closeToken = this.createToken(context.RBracket[0]);
|
|
745
|
+
}
|
|
746
|
+
return ast;
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* Converts cst token to identifier ast node.
|
|
750
|
+
*
|
|
751
|
+
* @param token CST token
|
|
752
|
+
* @param delimiter Quotation delimiter (none by default)
|
|
753
|
+
* @returns Identifier ast node
|
|
754
|
+
*/
|
|
755
|
+
tokenToIdentifier(token, delimiter = annotation_ast_nodes_1.Delimiter.none) {
|
|
756
|
+
return {
|
|
757
|
+
type: annotation_ast_nodes_1.IDENTIFIER_TYPE,
|
|
758
|
+
value: token.image,
|
|
759
|
+
range: this.tokenToRange(token),
|
|
760
|
+
quoted: delimiter !== annotation_ast_nodes_1.Delimiter.none
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* Converts CST token to separator ast node.
|
|
765
|
+
*
|
|
766
|
+
* @param token CST token
|
|
767
|
+
* @param delimiter Escaped value delimiter (none by default)
|
|
768
|
+
* @returns Separator ast node
|
|
769
|
+
*/
|
|
770
|
+
tokenToSeparator(token, delimiter = annotation_ast_nodes_1.Delimiter.none) {
|
|
771
|
+
return {
|
|
772
|
+
type: annotation_ast_nodes_1.SEPARATOR_TYPE,
|
|
773
|
+
value: token.image,
|
|
774
|
+
range: this.tokenToRange(token),
|
|
775
|
+
escaped: delimiter !== annotation_ast_nodes_1.Delimiter.none
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Tries to recover identifier from one of given separator tokens (adjusts its range).
|
|
780
|
+
*
|
|
781
|
+
* @param identifier Identifier CST token
|
|
782
|
+
* @param index Index of separator token to recover
|
|
783
|
+
* @param separatorTokens Array with separator tokens
|
|
784
|
+
* @returns Recovered from separator identifier or original identifier
|
|
785
|
+
*/
|
|
786
|
+
recoverIdentifiers(identifier, index, separatorTokens = []) {
|
|
787
|
+
const separator = separatorTokens[index - 1];
|
|
788
|
+
const fromErrorRecovery = identifier.isInsertedInRecovery && separator
|
|
789
|
+
? // Adjust range so it is the next character after dot
|
|
790
|
+
this.identifierFromSeparatorToken(separator)
|
|
791
|
+
: undefined;
|
|
792
|
+
if (fromErrorRecovery) {
|
|
793
|
+
return fromErrorRecovery;
|
|
794
|
+
}
|
|
795
|
+
return identifier;
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Converts separator CST token to identifier cst token.
|
|
799
|
+
*
|
|
800
|
+
* @param token Separator token
|
|
801
|
+
* @returns Identifier CST token with empty image nd adjusted range
|
|
802
|
+
*/
|
|
803
|
+
identifierFromSeparatorToken(token) {
|
|
804
|
+
var _a, _b;
|
|
805
|
+
// Adjust range so it is the next character after separator
|
|
806
|
+
return {
|
|
807
|
+
image: '',
|
|
808
|
+
startOffset: token.startOffset + 1,
|
|
809
|
+
startLine: token.startLine,
|
|
810
|
+
startColumn: ((_a = token.startColumn) !== null && _a !== void 0 ? _a : 0) + 1,
|
|
811
|
+
endOffset: token.endOffset,
|
|
812
|
+
endLine: token.endLine,
|
|
813
|
+
endColumn: token.endColumn,
|
|
814
|
+
tokenType: tokens_1.tokenMap.Identifier,
|
|
815
|
+
isInsertedInRecovery: true,
|
|
816
|
+
tokenTypeIdx: (_b = tokens_1.tokenMap.Identifier.tokenTypeIdx) !== null && _b !== void 0 ? _b : -1
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Creates empty identifier st token.
|
|
821
|
+
*
|
|
822
|
+
* @param start Start CST token
|
|
823
|
+
* @param end End CST token
|
|
824
|
+
* @returns Empty identifier CST token
|
|
825
|
+
*/
|
|
826
|
+
createEmptyIdentifier(start, end) {
|
|
827
|
+
var _a, _b, _c, _d;
|
|
828
|
+
return {
|
|
829
|
+
image: '',
|
|
830
|
+
startOffset: ((_a = start.endOffset) !== null && _a !== void 0 ? _a : 0) + 1,
|
|
831
|
+
startLine: start.endLine,
|
|
832
|
+
startColumn: ((_b = start.endColumn) !== null && _b !== void 0 ? _b : 0) + 1,
|
|
833
|
+
endOffset: end.startOffset - 1,
|
|
834
|
+
endLine: end.startLine,
|
|
835
|
+
endColumn: ((_c = end.startColumn) !== null && _c !== void 0 ? _c : 0) - 1,
|
|
836
|
+
tokenType: tokens_1.tokenMap.Identifier,
|
|
837
|
+
isInsertedInRecovery: true,
|
|
838
|
+
tokenTypeIdx: (_d = tokens_1.tokenMap.Identifier.tokenTypeIdx) !== null && _d !== void 0 ? _d : -1
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Extacts identifier tokens and delimiters from the given path segment cst node.
|
|
843
|
+
*
|
|
844
|
+
* @param segment Path segment node
|
|
845
|
+
* @returns Array of objects consisting of identifier token and delimiter
|
|
846
|
+
*/
|
|
847
|
+
getIdentifierToken(segment) {
|
|
848
|
+
var _a;
|
|
849
|
+
if ((0, utils_1.hasItems)(segment.children.NumberSign)) {
|
|
850
|
+
if ((0, utils_1.hasItems)(segment.children.Identifier)) {
|
|
851
|
+
segment.children.Identifier[0].image += '#';
|
|
852
|
+
}
|
|
853
|
+
if ((0, utils_1.hasItems)(segment.children.Identifier) && segment.children.Identifier.length > 1) {
|
|
854
|
+
segment.children.Identifier[0].image += segment.children.Identifier[1].image;
|
|
855
|
+
segment = this.setNewRangeForIdentifier(segment, 1, 'Identifier');
|
|
856
|
+
}
|
|
857
|
+
else {
|
|
858
|
+
segment = this.setNewRangeForIdentifier(segment, 0, 'NumberSign');
|
|
859
|
+
}
|
|
860
|
+
if ((0, utils_1.hasItems)(segment.children.Identifier)) {
|
|
861
|
+
return [
|
|
862
|
+
{
|
|
863
|
+
token: segment.children.Identifier[0],
|
|
864
|
+
delimiter: annotation_ast_nodes_1.Delimiter.none
|
|
865
|
+
}
|
|
866
|
+
];
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
else if ((0, utils_1.hasItems)(segment.children.Identifier, 2)) {
|
|
870
|
+
if (segment.children.Identifier[1].tokenTypeIdx === tokens_1.tokenMap.TermCastIdentifier.tokenTypeIdx) {
|
|
871
|
+
segment.children.Identifier[0].image += segment.children.Identifier[1].image;
|
|
872
|
+
segment = this.setNewRangeForIdentifier(segment, 1, 'Identifier');
|
|
873
|
+
}
|
|
874
|
+
if ((0, utils_1.hasItems)(segment.children.Identifier)) {
|
|
875
|
+
return [
|
|
876
|
+
{
|
|
877
|
+
token: segment.children.Identifier[0],
|
|
878
|
+
delimiter: annotation_ast_nodes_1.Delimiter.none
|
|
879
|
+
}
|
|
880
|
+
];
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
return ((_a = segment.children.Identifier) !== null && _a !== void 0 ? _a : []).map((token) => ({
|
|
884
|
+
token,
|
|
885
|
+
delimiter: annotation_ast_nodes_1.Delimiter.none
|
|
886
|
+
}));
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Sets new range end for the identifier in the given path segment.
|
|
890
|
+
*
|
|
891
|
+
* @param segment Path segment CST node
|
|
892
|
+
* @param index Index of an element within child grop to take range data from
|
|
893
|
+
* @param key Key of the children group
|
|
894
|
+
* @returns Updated path segment node
|
|
895
|
+
*/
|
|
896
|
+
setNewRangeForIdentifier(segment, index, key) {
|
|
897
|
+
var _a, _b, _c;
|
|
898
|
+
if ((0, utils_1.hasItems)(segment.children.Identifier)) {
|
|
899
|
+
segment.children.Identifier[0].endColumn = (_a = segment.children[key]) === null || _a === void 0 ? void 0 : _a[index].endColumn;
|
|
900
|
+
segment.children.Identifier[0].endLine = (_b = segment.children[key]) === null || _b === void 0 ? void 0 : _b[index].endLine;
|
|
901
|
+
segment.children.Identifier[0].endOffset = (_c = segment.children[key]) === null || _c === void 0 ? void 0 : _c[index].endOffset;
|
|
902
|
+
}
|
|
903
|
+
return segment;
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* Joins segment identifiers by given separators.
|
|
907
|
+
*
|
|
908
|
+
* @param segments Array with identifier tokens
|
|
909
|
+
* @param separators Array with separator tokens
|
|
910
|
+
* @returns String result
|
|
911
|
+
*/
|
|
912
|
+
joinSegments(segments, separators) {
|
|
913
|
+
let value = '';
|
|
914
|
+
const remainingSeparators = [...separators];
|
|
915
|
+
for (const segment of segments) {
|
|
916
|
+
value += segment.value;
|
|
917
|
+
const separator = remainingSeparators.shift();
|
|
918
|
+
if (separator) {
|
|
919
|
+
value += separator.value;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
return value;
|
|
923
|
+
}
|
|
924
|
+
/**
|
|
925
|
+
* Converts path children to path ast node.
|
|
926
|
+
*
|
|
927
|
+
* @param context Path node children
|
|
928
|
+
* @param location CST location
|
|
929
|
+
* @returns Path AST node
|
|
930
|
+
*/
|
|
931
|
+
path(context, location) {
|
|
932
|
+
var _a, _b, _c;
|
|
933
|
+
const segments = ((_a = context.pathSegment) !== null && _a !== void 0 ? _a : [])
|
|
934
|
+
.map((segment, i) => {
|
|
935
|
+
var _a, _b, _c, _d, _e;
|
|
936
|
+
const quotedIdentifiers = (_b = (_a = segment.children.quotedIdentifier) === null || _a === void 0 ? void 0 : _a.reduce((acc, quotedIdentifier) => {
|
|
937
|
+
return [
|
|
938
|
+
...acc,
|
|
939
|
+
...(quotedIdentifier.children.QuotedIdentifier || []).map((token, j) => {
|
|
940
|
+
var _a;
|
|
941
|
+
return ({
|
|
942
|
+
token: this.recoverIdentifiers(token, j, (_a = quotedIdentifier.children.PathSegmentSeparator) !== null && _a !== void 0 ? _a : []),
|
|
943
|
+
delimiter: annotation_ast_nodes_1.Delimiter.quoted
|
|
944
|
+
});
|
|
945
|
+
})
|
|
946
|
+
];
|
|
947
|
+
}, [])) !== null && _b !== void 0 ? _b : [];
|
|
948
|
+
const delimitedIdentifiers = ((_d = (_c = segment.children.delimitedIdentifier) === null || _c === void 0 ? void 0 : _c.reduce((acc, delimitedIdentifier) => {
|
|
949
|
+
if (!delimitedIdentifier.children.DelimitedIdentifier) {
|
|
950
|
+
return [
|
|
951
|
+
...acc,
|
|
952
|
+
{
|
|
953
|
+
token: this.createEmptyIdentifier(delimitedIdentifier.children.IdentifierStart[0], delimitedIdentifier.children.DelimitedIdentifierExit[0]),
|
|
954
|
+
delimiter: annotation_ast_nodes_1.Delimiter.exclamationSquareBrackets
|
|
955
|
+
}
|
|
956
|
+
];
|
|
957
|
+
}
|
|
958
|
+
return [
|
|
959
|
+
...acc,
|
|
960
|
+
...(delimitedIdentifier.children.DelimitedIdentifier || []).map((token, j) => {
|
|
961
|
+
var _a;
|
|
962
|
+
return ({
|
|
963
|
+
token: this.recoverIdentifiers(token, j, (_a = delimitedIdentifier.children.PathSegmentSeparator) !== null && _a !== void 0 ? _a : []),
|
|
964
|
+
delimiter: annotation_ast_nodes_1.Delimiter.exclamationSquareBrackets
|
|
965
|
+
});
|
|
966
|
+
})
|
|
967
|
+
];
|
|
968
|
+
}, [])) !== null && _d !== void 0 ? _d : []).map((identifier) => identifier);
|
|
969
|
+
const separator = ((_e = context.PathSegmentSeparator) !== null && _e !== void 0 ? _e : [])[i - 1];
|
|
970
|
+
const fromErrorRecovery = segment.recoveredNode && separator
|
|
971
|
+
? [{ token: this.identifierFromSeparatorToken(separator), delimiter: annotation_ast_nodes_1.Delimiter.none }]
|
|
972
|
+
: [];
|
|
973
|
+
const identifiers = this.getIdentifierToken(segment);
|
|
974
|
+
return [...identifiers, ...quotedIdentifiers, ...delimitedIdentifiers, ...fromErrorRecovery];
|
|
975
|
+
})
|
|
976
|
+
.reduce((acc, allSegments) => [...acc, ...allSegments], [])
|
|
977
|
+
.sort((a, b) => compareTokensByPosition(a.token, b.token))
|
|
978
|
+
.map(({ token, delimiter }) => this.tokenToIdentifier(token, delimiter));
|
|
979
|
+
const separators = [
|
|
980
|
+
...((_b = context.pathSegment) !== null && _b !== void 0 ? _b : []).map((segment) => {
|
|
981
|
+
var _a, _b, _c, _d;
|
|
982
|
+
const quotedIdentifiers = (_b = (_a = segment.children.quotedIdentifier) === null || _a === void 0 ? void 0 : _a.reduce((acc, quotedIdentifier) => {
|
|
983
|
+
var _a;
|
|
984
|
+
const childrenSeparators = (_a = quotedIdentifier.children.PathSegmentSeparator) !== null && _a !== void 0 ? _a : [];
|
|
985
|
+
return [
|
|
986
|
+
...acc,
|
|
987
|
+
...childrenSeparators.map((token) => ({
|
|
988
|
+
token,
|
|
989
|
+
delimiter: annotation_ast_nodes_1.Delimiter.quoted
|
|
990
|
+
}))
|
|
991
|
+
];
|
|
992
|
+
}, [])) !== null && _b !== void 0 ? _b : [];
|
|
993
|
+
const delimitedIdentifiers = (_d = (_c = segment.children.delimitedIdentifier) === null || _c === void 0 ? void 0 : _c.reduce((acc, delimitedIdentifier) => {
|
|
994
|
+
var _a;
|
|
995
|
+
if (!delimitedIdentifier.children.DelimitedIdentifier) {
|
|
996
|
+
return [
|
|
997
|
+
...acc,
|
|
998
|
+
{
|
|
999
|
+
token: this.createEmptyIdentifier(delimitedIdentifier.children.IdentifierStart[0], delimitedIdentifier.children.DelimitedIdentifierExit[0]),
|
|
1000
|
+
delimiter: annotation_ast_nodes_1.Delimiter.exclamationSquareBrackets
|
|
1001
|
+
}
|
|
1002
|
+
];
|
|
1003
|
+
}
|
|
1004
|
+
const childrenSeparators = (_a = delimitedIdentifier.children.PathSegmentSeparator) !== null && _a !== void 0 ? _a : [];
|
|
1005
|
+
return [
|
|
1006
|
+
...acc,
|
|
1007
|
+
...childrenSeparators.map((token) => ({
|
|
1008
|
+
token,
|
|
1009
|
+
delimiter: annotation_ast_nodes_1.Delimiter.exclamationSquareBrackets
|
|
1010
|
+
}))
|
|
1011
|
+
];
|
|
1012
|
+
}, [])) !== null && _d !== void 0 ? _d : [];
|
|
1013
|
+
return [...quotedIdentifiers, ...delimitedIdentifiers];
|
|
1014
|
+
}),
|
|
1015
|
+
((_c = context.PathSegmentSeparator) !== null && _c !== void 0 ? _c : []).map((token) => ({
|
|
1016
|
+
token,
|
|
1017
|
+
delimiter: annotation_ast_nodes_1.Delimiter.none
|
|
1018
|
+
}))
|
|
1019
|
+
]
|
|
1020
|
+
.reduce((acc, allSegments) => [...acc, ...allSegments], [])
|
|
1021
|
+
.sort((a, b) => compareTokensByPosition(a.token, b.token))
|
|
1022
|
+
.map(({ token, delimiter }) => this.tokenToSeparator(token, delimiter));
|
|
1023
|
+
const range = this.locationToRange(location);
|
|
1024
|
+
return {
|
|
1025
|
+
type: annotation_ast_nodes_1.PATH_TYPE,
|
|
1026
|
+
value: this.joinSegments(segments, separators),
|
|
1027
|
+
segments,
|
|
1028
|
+
separators,
|
|
1029
|
+
range
|
|
1030
|
+
};
|
|
1031
|
+
}
|
|
1032
|
+
/**
|
|
1033
|
+
* Extracts record property or embedded annotation from given record assignment.
|
|
1034
|
+
*
|
|
1035
|
+
* @param assignment Record assignment
|
|
1036
|
+
* @returns Property data
|
|
1037
|
+
*/
|
|
1038
|
+
getRecordProperty(assignment) {
|
|
1039
|
+
const assignmentRange = this.locationToRange(assignment.location);
|
|
1040
|
+
const name = this.getAssignmentKey(assignment.children, assignmentRange);
|
|
1041
|
+
let property;
|
|
1042
|
+
if (name.value.startsWith('@')) {
|
|
1043
|
+
property = {
|
|
1044
|
+
type: annotation_ast_nodes_1.ANNOTATION_TYPE,
|
|
1045
|
+
term: name,
|
|
1046
|
+
value: (0, utils_1.hasItems)(assignment.children.value)
|
|
1047
|
+
? this.visit(assignment.children.value[0])
|
|
1048
|
+
: undefined,
|
|
1049
|
+
range: assignmentRange
|
|
1050
|
+
};
|
|
1051
|
+
if (name.segments.length > 1 && name.segments[1].value.includes('#')) {
|
|
1052
|
+
property.qualifier = createQualifier(name);
|
|
1053
|
+
property.term.value = name.value.split('#')[0];
|
|
1054
|
+
}
|
|
1055
|
+
else if ((0, utils_1.hasItems)(assignment.children.NumberSign)) {
|
|
1056
|
+
property.qualifier = this.getQualifier(assignment.children);
|
|
1057
|
+
}
|
|
1058
|
+
return { property, kind: 'annotation' };
|
|
1059
|
+
}
|
|
1060
|
+
property = {
|
|
1061
|
+
type: annotation_ast_nodes_1.RECORD_PROPERTY_TYPE,
|
|
1062
|
+
name,
|
|
1063
|
+
value: (0, utils_1.hasItems)(assignment.children.value)
|
|
1064
|
+
? this.visit(assignment.children.value[0])
|
|
1065
|
+
: undefined,
|
|
1066
|
+
range: assignmentRange
|
|
1067
|
+
};
|
|
1068
|
+
return { property, kind: 'property' };
|
|
1069
|
+
}
|
|
1070
|
+
/**
|
|
1071
|
+
* Converts structure children to ast record node.
|
|
1072
|
+
*
|
|
1073
|
+
* @param context CST structure children
|
|
1074
|
+
* @param location CST location
|
|
1075
|
+
* @returns AST record node
|
|
1076
|
+
*/
|
|
1077
|
+
struct(context, location) {
|
|
1078
|
+
var _a;
|
|
1079
|
+
const range = this.locationToRange(location);
|
|
1080
|
+
const { properties: allProperties, annotations: allAnnotations } = ((_a = context.assignment) !== null && _a !== void 0 ? _a : [])
|
|
1081
|
+
.filter((assignment) => {
|
|
1082
|
+
return (0, utils_1.hasItems)(assignment.children.path) || (0, utils_1.hasItems)(assignment.children.value);
|
|
1083
|
+
})
|
|
1084
|
+
.reduce(({ annotations, properties }, assignment, assignmentIndex, assignments) => {
|
|
1085
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1086
|
+
const { property, kind } = this.getRecordProperty(assignment);
|
|
1087
|
+
if (kind === 'annotation') {
|
|
1088
|
+
annotations.push(property);
|
|
1089
|
+
}
|
|
1090
|
+
else {
|
|
1091
|
+
properties.push(property);
|
|
1092
|
+
}
|
|
1093
|
+
if ((0, utils_1.hasItems)(assignment.children.Colon) &&
|
|
1094
|
+
(!(0, utils_1.hasItems)(assignment.children.value) ||
|
|
1095
|
+
(0, utils_1.hasNaNOrUndefined)((_b = (_a = assignment.children.value[0]) === null || _a === void 0 ? void 0 : _a.location) === null || _b === void 0 ? void 0 : _b.startOffset))) {
|
|
1096
|
+
this.recoverFromMissingValue(assignment.children.Colon[0], property);
|
|
1097
|
+
}
|
|
1098
|
+
else if (((_c = assignment.children) === null || _c === void 0 ? void 0 : _c.value) &&
|
|
1099
|
+
((_d = assignment.children) === null || _d === void 0 ? void 0 : _d.value.length) &&
|
|
1100
|
+
((_f = (_e = assignment.children.value[0]) === null || _e === void 0 ? void 0 : _e.children) === null || _f === void 0 ? void 0 : _f.path) &&
|
|
1101
|
+
assignments[assignmentIndex + 1] &&
|
|
1102
|
+
!((_g = assignments[assignmentIndex + 1].children) === null || _g === void 0 ? void 0 : _g.path)) {
|
|
1103
|
+
// missing value and comma: path for next property has been wrongly consumed as value for current property
|
|
1104
|
+
const start = this.tokenToRange(assignment.children.Colon[0]).end;
|
|
1105
|
+
const end = (_h = this.locationToRange(assignment.children.value[0].location)) === null || _h === void 0 ? void 0 : _h.start;
|
|
1106
|
+
property.value = {
|
|
1107
|
+
type: annotation_ast_nodes_1.EMPTY_VALUE_TYPE,
|
|
1108
|
+
range: vscode_languageserver_types_1.Range.create(start, end !== null && end !== void 0 ? end : start)
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
property.colon = this.getColon(assignment);
|
|
1112
|
+
return { properties, annotations };
|
|
1113
|
+
}, { annotations: [], properties: [] });
|
|
1114
|
+
const commas = this.getCommaToken(context === null || context === void 0 ? void 0 : context.Comma);
|
|
1115
|
+
const ast = {
|
|
1116
|
+
type: annotation_ast_nodes_1.RECORD_TYPE,
|
|
1117
|
+
properties: allProperties,
|
|
1118
|
+
range,
|
|
1119
|
+
commas
|
|
1120
|
+
};
|
|
1121
|
+
if (allAnnotations.length) {
|
|
1122
|
+
ast.annotations = allAnnotations;
|
|
1123
|
+
}
|
|
1124
|
+
if (existsAndNotRecovered(context.LCurly)) {
|
|
1125
|
+
ast.openToken = this.createToken(context.LCurly[0]);
|
|
1126
|
+
}
|
|
1127
|
+
if (existsAndNotRecovered(context.RCurly)) {
|
|
1128
|
+
ast.closeToken = this.createToken(context.RCurly[0]);
|
|
1129
|
+
}
|
|
1130
|
+
return ast;
|
|
1131
|
+
}
|
|
1132
|
+
/**
|
|
1133
|
+
* Converts annotation assignment children to annotation ast node.
|
|
1134
|
+
*
|
|
1135
|
+
* @param context CST annotation assignment children
|
|
1136
|
+
* @param location CST location
|
|
1137
|
+
* @returns Annotation AST node
|
|
1138
|
+
*/
|
|
1139
|
+
assignment(context, location) {
|
|
1140
|
+
var _a, _b, _c;
|
|
1141
|
+
const range = this.locationToRange(location);
|
|
1142
|
+
const ast = {
|
|
1143
|
+
type: annotation_ast_nodes_1.ANNOTATION_TYPE,
|
|
1144
|
+
term: this.getAssignmentKey(context, range),
|
|
1145
|
+
range
|
|
1146
|
+
};
|
|
1147
|
+
if ((_a = context.Colon) === null || _a === void 0 ? void 0 : _a.length) {
|
|
1148
|
+
ast.colon = {
|
|
1149
|
+
type: annotation_ast_nodes_1.TOKEN_TYPE,
|
|
1150
|
+
value: context.Colon[0].image,
|
|
1151
|
+
range: this.tokenToRange(context.Colon[0])
|
|
1152
|
+
};
|
|
1153
|
+
}
|
|
1154
|
+
if ((0, utils_1.hasItems)(context.NumberSign)) {
|
|
1155
|
+
ast.qualifier = this.getQualifier(context);
|
|
1156
|
+
}
|
|
1157
|
+
// Flattened qualifier syntax handling
|
|
1158
|
+
if (!ast.qualifier && ast.term.segments.length && ast.term.segments[0].value.includes('#')) {
|
|
1159
|
+
ast.qualifier = createQualifier(ast.term);
|
|
1160
|
+
}
|
|
1161
|
+
if ((0, utils_1.hasItems)(context.value) && !(0, utils_1.hasNaNOrUndefined)((_c = (_b = context.value[0]) === null || _b === void 0 ? void 0 : _b.location) === null || _c === void 0 ? void 0 : _c.startOffset)) {
|
|
1162
|
+
ast.value = this.visit(context.value[0]);
|
|
1163
|
+
}
|
|
1164
|
+
else if ((0, utils_1.hasItems)(context.Colon)) {
|
|
1165
|
+
this.recoverFromMissingValue(context.Colon[0], ast);
|
|
1166
|
+
}
|
|
1167
|
+
return ast;
|
|
1168
|
+
}
|
|
1169
|
+
/**
|
|
1170
|
+
* Extracts assignment key.
|
|
1171
|
+
*
|
|
1172
|
+
* @param context CST assignment children
|
|
1173
|
+
* @param range CST range
|
|
1174
|
+
* @returns Empty path AST node
|
|
1175
|
+
*/
|
|
1176
|
+
getAssignmentKey(context, range) {
|
|
1177
|
+
if ((0, utils_1.hasItems)(context.path)) {
|
|
1178
|
+
return this.visit(context.path[0]);
|
|
1179
|
+
}
|
|
1180
|
+
const end = (0, utils_1.hasItems)(context.NumberSign)
|
|
1181
|
+
? this.tokenToRange(context.NumberSign[0]).start
|
|
1182
|
+
: this.tokenToRange(context.Colon[0]).start;
|
|
1183
|
+
const start = range ? (0, range_1.copyPosition)(range.start) : end;
|
|
1184
|
+
return {
|
|
1185
|
+
type: annotation_ast_nodes_1.PATH_TYPE,
|
|
1186
|
+
segments: [],
|
|
1187
|
+
separators: [],
|
|
1188
|
+
value: '',
|
|
1189
|
+
range: vscode_languageserver_types_1.Range.create(start, end)
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Recovers annotation or record property node when value is missng - sets up an empty value.
|
|
1194
|
+
*
|
|
1195
|
+
* @param colonToken Colon cst token
|
|
1196
|
+
* @param ast Annotation or property ast node
|
|
1197
|
+
*/
|
|
1198
|
+
recoverFromMissingValue(colonToken, ast) {
|
|
1199
|
+
// adjust range
|
|
1200
|
+
const nextToken = findNextToken(this.tokenVector, colonToken.endOffset);
|
|
1201
|
+
if (((nextToken === null || nextToken === void 0 ? void 0 : nextToken.image) === ',' || (nextToken === null || nextToken === void 0 ? void 0 : nextToken.image) === '}') && (nextToken === null || nextToken === void 0 ? void 0 : nextToken.startColumn)) {
|
|
1202
|
+
if (ast.range) {
|
|
1203
|
+
// annotation range should end before comma
|
|
1204
|
+
ast.range.end = this.tokenToRange(nextToken).start;
|
|
1205
|
+
}
|
|
1206
|
+
// Error recovery, insert PATH node
|
|
1207
|
+
const colonRange = this.tokenToRange(colonToken);
|
|
1208
|
+
const nextTokenRange = this.tokenToRange(nextToken);
|
|
1209
|
+
ast.value = {
|
|
1210
|
+
type: annotation_ast_nodes_1.EMPTY_VALUE_TYPE,
|
|
1211
|
+
range: vscode_languageserver_types_1.Range.create(colonRange.end, nextTokenRange.start)
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
const AstBuilder = new CstToAstVisitor();
|
|
1217
|
+
const buildAst = (cst, tokenVector, startPosition) => {
|
|
1218
|
+
AstBuilder.tokenVector = tokenVector;
|
|
1219
|
+
AstBuilder.startPosition = startPosition;
|
|
1220
|
+
const root = AstBuilder.visit(cst);
|
|
1221
|
+
if (root && (root.type === annotation_ast_nodes_1.ANNOTATION_TYPE || root.type === annotation_ast_nodes_1.ANNOTATION_GROUP_TYPE)) {
|
|
1222
|
+
return root;
|
|
1223
|
+
}
|
|
1224
|
+
return undefined;
|
|
1225
|
+
};
|
|
1226
|
+
exports.buildAst = buildAst;
|
|
1227
|
+
//# sourceMappingURL=ast.js.map
|