@sap/cds-compiler 4.9.2 → 5.0.6

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.
Files changed (88) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/bin/cds_remove_invalid_whitespace.js +2 -1
  3. package/bin/cdsc.js +15 -11
  4. package/bin/cdshi.js +1 -0
  5. package/doc/CHANGELOG_BETA.md +7 -0
  6. package/lib/api/main.js +7 -19
  7. package/lib/api/options.js +5 -11
  8. package/lib/api/trace.js +0 -1
  9. package/lib/base/builtins.js +1 -0
  10. package/lib/base/location.js +4 -1
  11. package/lib/base/message-registry.js +29 -29
  12. package/lib/base/messages.js +22 -26
  13. package/lib/base/model.js +0 -2
  14. package/lib/base/node-helpers.js +0 -1
  15. package/lib/checks/enricher.js +1 -5
  16. package/lib/checks/structuredAnnoExpressions.js +30 -0
  17. package/lib/checks/validator.js +8 -0
  18. package/lib/compiler/assert-consistency.js +4 -1
  19. package/lib/compiler/base.js +1 -1
  20. package/lib/compiler/builtins.js +18 -2
  21. package/lib/compiler/checks.js +2 -5
  22. package/lib/compiler/define.js +7 -7
  23. package/lib/compiler/extend.js +68 -33
  24. package/lib/compiler/generate.js +1 -1
  25. package/lib/compiler/index.js +23 -6
  26. package/lib/compiler/lsp-api.js +501 -2
  27. package/lib/compiler/populate.js +2 -2
  28. package/lib/compiler/propagator.js +1 -4
  29. package/lib/compiler/resolve.js +2 -15
  30. package/lib/compiler/shared.js +112 -31
  31. package/lib/compiler/tweak-assocs.js +2 -16
  32. package/lib/compiler/utils.js +2 -1
  33. package/lib/compiler/xsn-model.js +4 -0
  34. package/lib/edm/annotations/genericTranslation.js +95 -42
  35. package/lib/edm/csn2edm.js +16 -4
  36. package/lib/edm/edm.js +2 -3
  37. package/lib/edm/edmAnnoPreprocessor.js +1 -2
  38. package/lib/edm/edmPreprocessor.js +1 -7
  39. package/lib/gen/Dictionary.json +29 -2
  40. package/lib/gen/language.checksum +1 -1
  41. package/lib/gen/language.interp +2 -1
  42. package/lib/gen/languageParser.js +4995 -4817
  43. package/lib/json/csnVersion.js +1 -1
  44. package/lib/json/from-csn.js +4 -7
  45. package/lib/json/to-csn.js +23 -12
  46. package/lib/language/antlrParser.js +2 -2
  47. package/lib/language/errorStrategy.js +0 -1
  48. package/lib/language/genericAntlrParser.js +35 -12
  49. package/lib/language/multiLineStringParser.js +3 -2
  50. package/lib/language/textUtils.js +1 -0
  51. package/lib/main.d.ts +28 -9
  52. package/lib/main.js +7 -4
  53. package/lib/model/csnRefs.js +20 -4
  54. package/lib/model/csnUtils.js +0 -2
  55. package/lib/model/revealInternalProperties.js +1 -1
  56. package/lib/modelCompare/compare.js +1 -1
  57. package/lib/optionProcessor.js +28 -9
  58. package/lib/render/manageConstraints.js +1 -1
  59. package/lib/render/toCdl.js +36 -7
  60. package/lib/render/toSql.js +1 -0
  61. package/lib/render/utils/common.js +12 -9
  62. package/lib/render/utils/stringEscapes.js +1 -0
  63. package/lib/transform/db/applyTransformations.js +13 -8
  64. package/lib/transform/db/associations.js +62 -54
  65. package/lib/transform/db/constraints.js +23 -25
  66. package/lib/transform/db/expansion.js +1 -6
  67. package/lib/transform/db/flattening.js +89 -111
  68. package/lib/transform/db/temporal.js +3 -4
  69. package/lib/transform/db/views.js +0 -1
  70. package/lib/transform/draft/odata.js +51 -3
  71. package/lib/transform/effective/annotations.js +3 -2
  72. package/lib/transform/effective/flattening.js +135 -0
  73. package/lib/transform/effective/main.js +6 -6
  74. package/lib/transform/effective/types.js +13 -9
  75. package/lib/transform/forOdata.js +0 -2
  76. package/lib/transform/forRelationalDB.js +0 -19
  77. package/lib/transform/localized.js +7 -8
  78. package/lib/transform/odata/flattening.js +39 -31
  79. package/lib/transform/odata/typesExposure.js +5 -17
  80. package/lib/transform/transformUtils.js +1 -1
  81. package/lib/transform/translateAssocsToJoins.js +21 -3
  82. package/lib/utils/file.js +13 -7
  83. package/lib/utils/moduleResolve.js +59 -8
  84. package/lib/utils/term.js +3 -2
  85. package/package.json +7 -3
  86. package/share/messages/message-explanations.json +2 -0
  87. package/share/messages/type-unexpected-foreign-keys.md +52 -0
  88. package/share/messages/type-unexpected-on-condition.md +52 -0
@@ -1,5 +1,504 @@
1
1
  'use strict';
2
2
 
3
- // Placeholder for future LSP API.
3
+ // API for `@sap/cds-lsp`.
4
+ //
5
+ // THIS FILE IS CONSIDERED INTERNAL!
6
+ // We do not guarantee stability for any project besides the CAP LSP server.
7
+ //
8
+ // This files includes an iterator over "semantic tokens" in an XSN model.
9
+ // "Semantic tokens" are identifiers, but also the "return" parameter.
10
+ // See `internalDoc/lsp/IdentifierCrawling.md` for details.
4
11
 
5
- module.exports = {};
12
+ const { CompilerAssertion } = require('../base/error');
13
+ const $inferred = Symbol.for( 'cds.$inferred' );
14
+
15
+ // TODO: Remove hints; they should not be necessary in the best case
16
+ const HINTS = {
17
+ USING_ALIAS: 'using-alias',
18
+ DEFINITION_NAME: 'definition',
19
+ NAMESPACE_STATEMENT: 'namespace-statement',
20
+ };
21
+
22
+ // eslint-disable-next-line no-unused-vars
23
+ class LspSemanticTokenEvent {
24
+ event; // 'reference' | 'definition',
25
+ semanticToken;
26
+ node;
27
+ hint; // TODO: Remove
28
+ }
29
+
30
+ /**
31
+ * All actions to report semantic tokens in a model.
32
+ */
33
+ const artifactActions = {
34
+ __proto__: null,
35
+
36
+ // e.g. sources or services
37
+ artifacts: dictOf( artifactTokens ),
38
+ extensions: arrayOf( extensionTokens ),
39
+ namespace: namespaceTokens,
40
+ // e.g. via CSN input
41
+ vocabularies: dictOf( artifactTokens ),
42
+ definitions: dictOf( artifactTokens ),
43
+
44
+ extern: artifactTokens,
45
+ name: definitionNameTokens,
46
+ path: pathReferenceTokens,
47
+
48
+ type: artifactTokens,
49
+ target: artifactTokens,
50
+ targetAspect: artifactTokens,
51
+ targetElement: artifactTokens,
52
+ returns: returnsTokens,
53
+ items: artifactTokens,
54
+ elements: elementsTokens,
55
+
56
+ enum: dictOf( artifactTokens ),
57
+ foreignKeys: dictOf( artifactTokens ),
58
+ actions: dictOf( artifactTokens ),
59
+ params: dictOf( artifactTokens ),
60
+ mixin: dictOf( artifactTokens ),
61
+ excludingDict: dictOf( nameAsReference ),
62
+
63
+ // Don't crawl `$tableAliases`, as they are set multiple times in queries
64
+ // via different `$tableAliases`.
65
+ // $tableAliases: null,
66
+
67
+ // NOT $queries, as that doesn't cover UNIONs (e.g. `orderBy` vs `$orderBy`)
68
+ query: artifactTokens,
69
+
70
+ from: artifactTokens,
71
+ includes: arrayOf( artifactTokens ),
72
+ columns: arrayOf( artifactTokens ),
73
+ expand: arrayOf( artifactTokens ),
74
+ inline: arrayOf( artifactTokens ),
75
+
76
+ args: argsTokens,
77
+ on: artifactTokens,
78
+ default: artifactTokens,
79
+ value: artifactTokens,
80
+ sym: enumSymToken,
81
+ where: artifactTokens,
82
+ groupBy: artifactTokens,
83
+ orderBy: artifactTokens,
84
+ having: artifactTokens,
85
+ suffix: artifactTokens,
86
+ limit: artifactTokens,
87
+ rows: artifactTokens,
88
+ offset: artifactTokens,
89
+
90
+ '@': annotationTokens,
91
+ };
92
+
93
+ /** Returns a generator that applies the given function on all entries and yields the result. */
94
+ function dictOf( func ) {
95
+ return function* dictionary( dict ) {
96
+ for (const [ item ] of iterateGeneric({ dict }, 'dict'))
97
+ yield* func( item );
98
+ };
99
+ }
100
+
101
+ /** Returns a generator that applies the given function on all entries and yields the result. */
102
+ function arrayOf( func ) {
103
+ return function* array( arr ) {
104
+ if (!Array.isArray(arr))
105
+ return;
106
+ for (const item of arr)
107
+ yield* func( item );
108
+ };
109
+ }
110
+
111
+ /** Generator equivalent of iterateGeneric of forEachGeneric() */
112
+ function* iterateGeneric( obj, prop ) {
113
+ const dict = obj[prop];
114
+ if (!dict)
115
+ return;
116
+
117
+ for (const name in dict) {
118
+ obj = dict[name];
119
+ if (Array.isArray( obj )) {
120
+ for (const item of obj)
121
+ yield [ item, name, prop ]; // parser or source duplicates (e.g. USING vs definition)
122
+ }
123
+ else {
124
+ yield [ obj, name, prop ];
125
+ if (Array.isArray( obj.$duplicates )) { // redefinitions
126
+ for (const dup of obj.$duplicates)
127
+ yield [ dup, name, prop ];
128
+ }
129
+ }
130
+ }
131
+ }
132
+
133
+ /**
134
+ * A generator that yields all semantic tokens in an XSN model.
135
+ * Semantic tokens include identifiers (references/definitions) and the "returns" parameter.
136
+ *
137
+ * @param {XSN.Model} xsn
138
+ * @param {CSN.Options} options
139
+ * @returns {Generator<LspSemanticTokenEvent>}
140
+ */
141
+ function* traverseSemanticTokens( xsn, options ) {
142
+ if (!xsn)
143
+ throw new CompilerAssertion('Expected valid XSN model for traverseSemanticTokens(…)');
144
+ if (!options)
145
+ throw new CompilerAssertion('Expected valid options for traverseSemanticTokens(…)');
146
+
147
+ if (xsn.sources)
148
+ yield* dictOf( artifactTokens )( xsn.sources );
149
+ }
150
+
151
+ /**
152
+ * Report semantic tokens in artifacts, including definitions, elements, params, etc.
153
+ *
154
+ * @param {XSN.Artifact} art
155
+ * @returns {Generator<LspSemanticTokenEvent>}
156
+ */
157
+ function* artifactTokens( art ) {
158
+ if (!art || art.builtin || art.$inferred)
159
+ return null;
160
+
161
+ if (Array.isArray( art )) {
162
+ for (const entry of art)
163
+ yield* artifactTokens( entry );
164
+ return null;
165
+ }
166
+
167
+ for (const prop in art) {
168
+ if (artifactActions[prop])
169
+ yield* artifactActions[prop](art[prop], art);
170
+ else if (prop.charAt(0) === '@')
171
+ yield* artifactActions['@'](art[prop], art);
172
+ }
173
+
174
+ return null;
175
+ }
176
+
177
+ /**
178
+ * For an extension, yield all semantic tokens.
179
+ * We don't use `artifactTokens` for it, because extensions are a special case:
180
+ * - they have a name, but actually refer to some other artifact.
181
+ * - their artifacts such as elements may overlap with existing definitions, because
182
+ * extensions are applied; if they were applied, `_parent` does not point to the
183
+ * extension, which means we can't use it to skip them in `artifactTokens`.
184
+ * - we only need to handle `annotate` and `extend` kinds specifically:
185
+ * if an extension was not applied, pass it to `artifactTokens`;
186
+ * if an extension was applied, we only need to report its name (i.e. reference)
187
+ * and traverse over all artifacts
188
+ *
189
+ * @param {XSN.Extension} ext
190
+ * @returns {Generator<LspSemanticTokenEvent>}
191
+ */
192
+ function* extensionTokens( ext ) {
193
+ if (ext.kind !== 'extend' && ext.kind !== 'annotate')
194
+ return null;
195
+
196
+ const wasApplied = ext.name._artifact && !ext.name._artifact.$inferred;
197
+ if (!wasApplied) {
198
+ yield* artifactTokens( ext );
199
+ return null;
200
+ }
201
+
202
+ yield* nameAsReference( ext );
203
+
204
+ // We need to traverse all dictionaries that could themselves contain
205
+ // extensions. Enum extensions or columns don't need to be traversed,
206
+ // for example, because there can't be inner extensions.
207
+ yield* dictOf( extensionTokens )( ext.params );
208
+ yield* dictOf( extensionTokens )( ext.actions );
209
+ yield* dictOf( extensionTokens )( ext.elements );
210
+
211
+ if (ext.returns)
212
+ yield* extensionTokens( ext.returns );
213
+
214
+ // Artifact extensions are always definitions, and can't have nested `extend`s,
215
+ // hence no need to traverse them with `extensionTokens`.
216
+ yield* dictOf( artifactTokens )( ext.artifacts );
217
+
218
+ return null;
219
+ }
220
+
221
+ /**
222
+ * Report all semantic tokens in an annotation assignment.
223
+ *
224
+ * @param {XSN.Artifact} anno
225
+ * @returns {Generator<LspSemanticTokenEvent>}
226
+ */
227
+ function* annotationTokens( anno ) {
228
+ // TODO: Also report annotation names
229
+ if (anno.kind === '$annotation')
230
+ yield* annotationValueTokens( anno );
231
+ }
232
+
233
+ function* argsTokens( args, art ) {
234
+ if (Array.isArray(args)) {
235
+ // e.g. unnamed function arguments
236
+ yield* arrayOf( artifactTokens )( args );
237
+ }
238
+ else {
239
+ // e.g. named arguments
240
+ for (const [ param ] of iterateGeneric( art, 'args' )) {
241
+ yield* nameAsReference( param );
242
+ yield* artifactTokens( param );
243
+ }
244
+ }
245
+ }
246
+
247
+ function* enumSymToken( sym, expr ) {
248
+ yield {
249
+ event: 'reference',
250
+ semanticToken: expr.sym,
251
+ node: expr,
252
+ hint: undefined,
253
+ };
254
+ }
255
+
256
+ /**
257
+ * A namespace is always considered a reference and not a definition.
258
+ *
259
+ * @param {XSN.Artifact} def
260
+ * @returns {Generator<LspSemanticTokenEvent>}
261
+ */
262
+ function* namespaceTokens( def ) {
263
+ if (!def.name)
264
+ return null;
265
+
266
+ for (let i = 0; i < def.name.path.length; ++i) {
267
+ yield {
268
+ event: 'reference',
269
+ semanticToken: def.name.path[i],
270
+ node: def,
271
+ hint: (i === def.name.path.length - 1) ? HINTS.NAMESPACE_STATEMENT : null,
272
+ };
273
+ }
274
+
275
+ return null;
276
+ }
277
+
278
+ /**
279
+ * An annotation value may contain expressions which we need to report.
280
+ *
281
+ * @param {object} anno
282
+ * @returns {Generator<LspSemanticTokenEvent>}
283
+ */
284
+ function* annotationValueTokens( anno ) {
285
+ if (Array.isArray(anno)) {
286
+ for (const entry of anno)
287
+ yield* annotationValueTokens( entry );
288
+ }
289
+ else if (anno.$tokenTexts) {
290
+ yield* artifactTokens( anno );
291
+ }
292
+ else if (Array.isArray(anno.val)) {
293
+ yield* annotationValueTokens( anno.val );
294
+ }
295
+ else if (anno.struct) {
296
+ for (const [ struct ] of iterateGeneric( anno, 'struct' ))
297
+ yield* annotationValueTokens( struct );
298
+ }
299
+ }
300
+
301
+ /**
302
+ * A `returns` structure may contain sub-elements. But we report the `returns`
303
+ * token as well, as it is considered a token with semantic value.
304
+ *
305
+ * @param {XSN.Artifact} art
306
+ * @returns {Generator<LspSemanticTokenEvent>}
307
+ */
308
+ function* returnsTokens( art ) {
309
+ if (art.kind === 'param') {
310
+ // report the `returns` parameter
311
+ yield {
312
+ event: 'definition',
313
+ semanticToken: art.name,
314
+ node: art,
315
+ hint: undefined,
316
+ };
317
+ yield* artifactTokens( art );
318
+ }
319
+ }
320
+
321
+ /**
322
+ * Report elements if they should be traversed. They are not always traversed
323
+ * to avoid duplication due to `expand` and `columns` also being traversed.
324
+ *
325
+ * @param {Record<string, XSN.Artifact>} elements
326
+ * @param {XSN.Artifact} art
327
+ * @returns {Generator<LspSemanticTokenEvent>}
328
+ */
329
+ function* elementsTokens( elements, art ) {
330
+ if (shouldTraverseElements( art ))
331
+ yield* dictOf( artifactTokens )( elements );
332
+ }
333
+
334
+ /**
335
+ * Report all references in `ref`.
336
+ *
337
+ * @returns {Generator<LspSemanticTokenEvent>}
338
+ */
339
+ function* pathReferenceTokens( path, ref, user = ref, hint = null ) {
340
+ if (!path)
341
+ return null;
342
+
343
+ // don't report cds.Association/cds.Composition
344
+ // TODO: Or report the `Association` keyword, similar to `returns`?
345
+ if (path.length === 1 && ref._artifact?.category === 'relation')
346
+ return null;
347
+
348
+ yield* artifactTokens( path );
349
+
350
+ // parser prepends a fake `type of` segment, which we need to skip
351
+ const root = ref.scope === 'typeOf' ? 1 : 0;
352
+ for (let i = root; i < path.length; ++i) {
353
+ if (!path[i].$inferred) { // e.g. `id` when expanded from `$user`
354
+ yield {
355
+ event: 'reference',
356
+ semanticToken: path[i],
357
+ node: user,
358
+ hint,
359
+ };
360
+ }
361
+ }
362
+
363
+ return null;
364
+ }
365
+
366
+ /**
367
+ * Some XSN nodes such as entries in `excludingDict` or named arguments are references
368
+ * but don't have a `path` property, only a `name` property. Report such names
369
+ * as references.
370
+ *
371
+ * @returns {Generator<LspSemanticTokenEvent>}
372
+ */
373
+ function* nameAsReference( ref, hint = null ) {
374
+ if (!ref.name || ref.name.$inferred)
375
+ return null;
376
+
377
+ if (ref.name.path) {
378
+ yield* pathReferenceTokens( ref.name.path, ref.name, ref, hint );
379
+ }
380
+ else {
381
+ yield {
382
+ event: 'reference',
383
+ semanticToken: ref.name,
384
+ node: ref,
385
+ hint,
386
+ };
387
+ }
388
+ return null;
389
+ }
390
+
391
+ /**
392
+ * Traverse the name of a definition, and report N-1 path steps as references
393
+ * and of course the definition itself.
394
+ *
395
+ * @returns {Generator<LspSemanticTokenEvent>}
396
+ */
397
+ function* definitionNameTokens( name, art ) {
398
+ if (!art.kind)
399
+ return null; // e.g. parameter references
400
+ if (art.kind === '$annotation')
401
+ return null; // annotation name, e.g. in `@anno: (elem)`
402
+
403
+ if ((name.$inferred && name.$inferred !== 'as') ||
404
+ art.kind === 'select' || art.kind === '$join') {
405
+ // Internal names such as numbers for SELECTs or the `$internal` names must
406
+ // not be reported.
407
+ return null;
408
+ }
409
+
410
+ if (art.kind === 'extend' || art.kind === 'annotate') {
411
+ yield* nameAsReference( art );
412
+ return null;
413
+ }
414
+
415
+ // Report references in a name (N-1 path steps).
416
+ for (let i = 0; i < name.path?.length - 1; ++i) {
417
+ yield {
418
+ event: 'reference',
419
+ semanticToken: name.path[i],
420
+ node: art,
421
+ hint: HINTS.DEFINITION_NAME,
422
+ };
423
+ }
424
+
425
+ const hint = art.kind === 'using' ? HINTS.USING_ALIAS : null;
426
+
427
+ if (name.path) {
428
+ // Only take the last path step; all others are considered references.
429
+ const implicitName = name.path[name.path.length - 1];
430
+ yield {
431
+ event: 'definition',
432
+ semanticToken: implicitName,
433
+ node: art,
434
+ hint,
435
+ };
436
+ }
437
+ else if (name.id) {
438
+ // Not all names have a path; some (e.g. parameters) only have an ID.
439
+ yield {
440
+ event: 'definition',
441
+ semanticToken: name,
442
+ node: art,
443
+ hint,
444
+ };
445
+ }
446
+
447
+ return null;
448
+ }
449
+
450
+ /**
451
+ * Returns true if `elements` of the given `art` should be traversed.
452
+ * Elements are _not_ traversed, e.g. for `expand`, to avoid duplicates.
453
+ *
454
+ * @returns {boolean}
455
+ */
456
+ function shouldTraverseElements( art ) {
457
+ return (
458
+ // $expand: 'origin' -> normal expansion
459
+ // $expand: 'annotate' -> additional annotation (needs to traverse annotation expressions)
460
+ art.$expand !== 'origin' && !art.elements[$inferred] && (
461
+ // sub-elements are always traversed except for `expand`, which is handled on its own.
462
+ art.kind === 'element' && !art.expand ||
463
+ // all non-query elements are traversed; because `_main` on bound actions may point
464
+ // to a query, we handle parameters explicitly.
465
+ art.kind === 'param' || !(art._main || art).$queries
466
+ )
467
+ );
468
+ }
469
+
470
+ /**
471
+ * Given a LspSemanticTokenEvent, returns a generator that yields the referenced
472
+ * object and its origin's until the deepest entry is found.
473
+ *
474
+ * @param obj
475
+ * @returns {Generator<*, void, *>}
476
+ */
477
+ function* getSemanticTokenOrigin( obj ) {
478
+ let ref = obj.semanticToken;
479
+ if (obj.event === 'definition') {
480
+ ref = obj.node;
481
+ }
482
+ else {
483
+ if (!ref?._artifact)
484
+ return; // unknown -> abort
485
+ // take first artifact for duplicates (best effort)
486
+ ref = Array.isArray(ref._artifact) ? ref._artifact[0] : ref._artifact;
487
+ yield ref;
488
+ }
489
+
490
+ if (!ref._effectiveType)
491
+ return; // abort for unresolved references and cyclic ones
492
+
493
+ while (ref._origin) {
494
+ yield ref._origin;
495
+ ref = ref._origin;
496
+ if (!ref || typeof ref === 'string')
497
+ break;
498
+ }
499
+ }
500
+
501
+ module.exports = {
502
+ traverseSemanticTokens,
503
+ getSemanticTokenOrigin,
504
+ };
@@ -1069,10 +1069,10 @@ function populate( model ) {
1069
1069
  else {
1070
1070
  // referred (and probably inferred) assoc (without a user-provided target at that place)
1071
1071
  // HINT: consider bin/cdsv2m.js when changing the following message text
1072
- // No grouped and sub messages yet (TODO v5): mention at all target places with all assocs
1072
+ // No grouped and sub messages yet (TODO v6): mention at all target places with all assocs
1073
1073
  const withAnno = annotationVal( exposed[0]['@cds.redirection.target'] );
1074
1074
  for (const proj of exposed) {
1075
- // TODO: def-ambiguous-target (just v5, as the current is infamous and used in options),
1075
+ // TODO: def-ambiguous-target (just v6, as the current is infamous and used in options),
1076
1076
  message( 'redirected-implicitly-ambiguous',
1077
1077
  [ weakLocation( proj.name.location ), proj ],
1078
1078
  {
@@ -13,7 +13,6 @@ const {
13
13
  forEachMember,
14
14
  forEachGeneric,
15
15
  isDeprecatedEnabled,
16
- isBetaEnabled,
17
16
  } = require( '../base/model');
18
17
  const {
19
18
  setLink,
@@ -56,7 +55,6 @@ function propagate( model ) {
56
55
  enum: expensive,
57
56
  params: expensive, // actually only with parent action
58
57
  returns,
59
- $filtered: annotation, // TODO(v5): Remove
60
58
  $enclosed: annotation,
61
59
  };
62
60
  const ruleToFunction = {
@@ -75,8 +73,7 @@ function propagate( model ) {
75
73
  const { warning, throwWithError } = model.$messageFunctions;
76
74
 
77
75
  forEachDefinition( model, run );
78
- if (isBetaEnabled( model.options, 'v5preview' ))
79
- forEachGeneric( model, 'vocabularies', run );
76
+ forEachGeneric( model, 'vocabularies', run );
80
77
 
81
78
  // TODO: move 'virtual' handling/checks to resolver if
82
79
  // 'deprecated.oldVirtualNotNullPropagation' is gone
@@ -88,6 +88,7 @@ function resolve( model ) {
88
88
  } = model.$messageFunctions;
89
89
  const {
90
90
  resolvePath,
91
+ resolveDefinitionName,
91
92
  traverseExpr,
92
93
  createRemainingAnnotateStatements,
93
94
  effectiveType,
@@ -442,7 +443,7 @@ function resolve( model ) {
442
443
  obj.items = items;
443
444
  obj.$expand = 'origin';
444
445
  }
445
- if (obj.items) { // TODO: make this a while in v5 (also items proxy)
446
+ if (obj.items) { // TODO: make this a while in v6 (also items proxy)
446
447
  obj = obj.items || obj; // the object which has type properties
447
448
  effectiveType( obj );
448
449
  }
@@ -1266,7 +1267,6 @@ function resolve( model ) {
1266
1267
  { art: target, '#': variant, keyword: op || '' }, {
1267
1268
  std: 'Redirection involves the complex view $(ART)',
1268
1269
  target: 'The redirected target $(ART) is a complex view',
1269
- // eslint-disable-next-line max-len
1270
1270
  targetOp: 'The redirected target $(ART) is a complex view with $(KEYWORD)',
1271
1271
  } );
1272
1272
  break;
@@ -1360,19 +1360,6 @@ function resolve( model ) {
1360
1360
  // General resolver functions
1361
1361
  //--------------------------------------------------------------------------
1362
1362
 
1363
- // Resolve the n-1 path steps before the definition name for LSP.
1364
- function resolveDefinitionName( art ) {
1365
- const path = art?.name?.path;
1366
- if (!art || art._main || !path || path.length <= 1)
1367
- return;
1368
-
1369
- let name = art.name.id;
1370
- for (let i = path.length - 1; i > 0; --i) {
1371
- name = name.substring(0, name.length - path[i].id.length - 1);
1372
- setArtifactLink( path[i - 1], model.definitions[name] || false );
1373
- }
1374
- }
1375
-
1376
1363
  // Resolve the type and its arguments if applicable.
1377
1364
  function resolveTypeExpr( art, user ) {
1378
1365
  const typeArt = resolvePath( art.type, 'type', user );