@sap/cds-compiler 3.1.2 → 3.4.0
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 +101 -3
- package/bin/cdsc.js +4 -2
- package/doc/CHANGELOG_BETA.md +35 -0
- package/lib/api/main.js +153 -29
- package/lib/api/validate.js +8 -3
- package/lib/base/dictionaries.js +6 -6
- package/lib/base/error.js +2 -2
- package/lib/base/keywords.js +106 -24
- package/lib/base/message-registry.js +177 -79
- package/lib/base/messages.js +78 -57
- package/lib/base/model.js +2 -1
- package/lib/checks/actionsFunctions.js +1 -1
- package/lib/checks/annotationsOData.js +2 -2
- package/lib/checks/arrayOfs.js +15 -7
- package/lib/checks/cdsPersistence.js +1 -1
- package/lib/checks/checkForTypes.js +53 -0
- package/lib/checks/defaultValues.js +4 -2
- package/lib/checks/elements.js +81 -6
- package/lib/checks/foreignKeys.js +12 -13
- package/lib/checks/invalidTarget.js +10 -11
- package/lib/checks/managedInType.js +21 -15
- package/lib/checks/nullableKeys.js +1 -1
- package/lib/checks/onConditions.js +9 -9
- package/lib/checks/parameters.js +23 -0
- package/lib/checks/queryNoDbArtifacts.js +1 -1
- package/lib/checks/selectItems.js +1 -1
- package/lib/checks/sql-snippets.js +12 -10
- package/lib/checks/types.js +2 -2
- package/lib/checks/utils.js +17 -7
- package/lib/checks/validator.js +36 -14
- package/lib/compiler/assert-consistency.js +21 -13
- package/lib/compiler/builtins.js +8 -0
- package/lib/compiler/checks.js +57 -40
- package/lib/compiler/define.js +139 -69
- package/lib/compiler/extend.js +319 -50
- package/lib/compiler/finalize-parse-cdl.js +14 -9
- package/lib/compiler/kick-start.js +2 -35
- package/lib/compiler/populate.js +111 -68
- package/lib/compiler/propagator.js +5 -3
- package/lib/compiler/resolve.js +71 -108
- package/lib/compiler/shared.js +82 -54
- package/lib/compiler/tweak-assocs.js +26 -14
- package/lib/compiler/utils.js +13 -2
- package/lib/edm/annotations/genericTranslation.js +10 -7
- package/lib/edm/csn2edm.js +11 -11
- package/lib/edm/edm.js +17 -9
- package/lib/edm/edmPreprocessor.js +53 -30
- package/lib/edm/edmUtils.js +7 -2
- package/lib/gen/Dictionary.json +14 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +3 -2
- package/lib/gen/languageParser.js +4312 -4186
- package/lib/inspect/inspectModelStatistics.js +1 -1
- package/lib/inspect/inspectPropagation.js +23 -9
- package/lib/json/csnVersion.js +13 -13
- package/lib/json/from-csn.js +161 -172
- package/lib/json/to-csn.js +70 -10
- package/lib/language/.eslintrc.json +4 -0
- package/lib/language/antlrParser.js +8 -11
- package/lib/language/docCommentParser.js +1 -2
- package/lib/language/errorStrategy.js +54 -27
- package/lib/language/genericAntlrParser.js +140 -93
- package/lib/language/language.g4 +57 -33
- package/lib/language/multiLineStringParser.js +75 -63
- package/lib/main.d.ts +3 -6
- package/lib/main.js +1 -0
- package/lib/model/.eslintrc.json +13 -0
- package/lib/model/api.js +4 -2
- package/lib/model/csnRefs.js +78 -50
- package/lib/model/csnUtils.js +272 -222
- package/lib/model/enrichCsn.js +41 -31
- package/lib/model/revealInternalProperties.js +61 -57
- package/lib/model/sortViews.js +35 -31
- package/lib/modelCompare/compare.js +52 -18
- package/lib/modelCompare/filter.js +83 -0
- package/lib/optionProcessor.js +10 -1
- package/lib/render/manageConstraints.js +11 -7
- package/lib/render/toCdl.js +151 -106
- package/lib/render/toHdbcds.js +8 -6
- package/lib/render/toRename.js +4 -4
- package/lib/render/toSql.js +17 -7
- package/lib/render/utils/common.js +27 -9
- package/lib/render/utils/sql.js +5 -5
- package/lib/sql-identifier.js +7 -0
- package/lib/transform/db/applyTransformations.js +32 -3
- package/lib/transform/db/assertUnique.js +27 -38
- package/lib/transform/db/expansion.js +92 -41
- package/lib/transform/db/flattening.js +1 -1
- package/lib/transform/db/temporal.js +3 -1
- package/lib/transform/db/transformExists.js +8 -2
- package/lib/transform/db/views.js +42 -13
- package/lib/transform/draft/db.js +2 -2
- package/lib/transform/forOdataNew.js +10 -7
- package/lib/transform/{forHanaNew.js → forRelationalDB.js} +18 -12
- package/lib/transform/localized.js +29 -20
- package/lib/transform/odata/toFinalBaseType.js +8 -11
- package/lib/transform/odata/typesExposure.js +2 -1
- package/lib/transform/parseExpr.js +245 -0
- package/lib/transform/transformUtilsNew.js +122 -51
- package/lib/transform/translateAssocsToJoins.js +17 -16
- package/lib/utils/moduleResolve.js +5 -5
- package/lib/utils/objectUtils.js +3 -3
- package/lib/utils/term.js +5 -5
- package/package.json +2 -2
- package/share/messages/anno-duplicate-unrelated-layer.md +6 -6
- package/share/messages/check-proper-type-of.md +4 -4
- package/share/messages/check-proper-type.md +2 -2
- package/share/messages/duplicate-autoexposed.md +4 -4
- package/share/messages/extend-repeated-intralayer.md +4 -5
- package/share/messages/extend-unrelated-layer.md +4 -4
- package/share/messages/message-explanations.json +3 -1
- package/share/messages/redirected-to-ambiguous.md +7 -6
- package/share/messages/redirected-to-complex.md +63 -0
- package/share/messages/redirected-to-unrelated.md +6 -5
- package/share/messages/rewrite-not-supported.md +4 -4
- package/share/messages/{syntax-expected-integer.md → syntax-expecting-integer.md} +4 -4
- package/share/messages/wildcard-excluding-one.md +37 -0
package/lib/compiler/define.js
CHANGED
|
@@ -1,15 +1,31 @@
|
|
|
1
|
-
// Compiler phase "define": transform dictionary of AST-like
|
|
1
|
+
// Compiler phase 1 = "define": transform dictionary of AST-like XSNs into XSN
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
//
|
|
3
|
+
// The 'define' phase (function 'define' below) is the first phase of the compile
|
|
4
|
+
// function. In it, the compiler
|
|
5
|
+
//
|
|
6
|
+
// - collects definitions and extensions from the XSN representation of CDL and
|
|
7
|
+
// CSN sources (“ASTs”) into _one_ XSN model,
|
|
8
|
+
// - sets “structural” links between XSN nodes and completes the “name”,
|
|
9
|
+
// some links and names inside `extensions` are set at a later stage
|
|
10
|
+
// - reports errors for: “late” syntax errors (when it is more convenient to do
|
|
11
|
+
// it here instead of doing it in both CDL and CSN parser), “structural” errors
|
|
12
|
+
// and “duplicate definition errors”
|
|
13
|
+
|
|
14
|
+
// The 'define' phase is the only compile() phase which is also called for
|
|
15
|
+
// parse.cdl. See file ./finalize-parse-cdl.js for details.
|
|
16
|
+
|
|
17
|
+
// --------- TODO: begin in extra markdown document -----------------------------
|
|
18
|
+
|
|
19
|
+
// An XSN for a source looks like
|
|
20
|
+
// { kind: 'source', artifacts: <dictionary of artifact defs>, namespace: {}, ... }
|
|
5
21
|
//
|
|
6
22
|
// The property `artifacts` of a source contains the top-level definitions.
|
|
7
23
|
// Definitions inside a context are not listed here (as opposed to
|
|
8
24
|
// `definitions`, see below), but inside the property `artifacts` of that context.
|
|
9
25
|
|
|
10
|
-
// The define phase (function 'define' below) enriches a dictionary of
|
|
11
|
-
// (file names to) AST-like
|
|
12
|
-
// is called "augmented CSN":
|
|
26
|
+
// The 'define' phase (function 'define' below) enriches a dictionary of
|
|
27
|
+
// (file names to) AST-like XSNs and restructure them a little bit, the result
|
|
28
|
+
// is called XSN ("augmented CSN"):
|
|
13
29
|
// { sources: <dictionary of ASTs>, definitions: <dictionary of artifact defs> }
|
|
14
30
|
//
|
|
15
31
|
// The property `sources` is the input argument (dictionary of source ASTs).
|
|
@@ -20,14 +36,8 @@
|
|
|
20
36
|
// objects as the definitions accessible via `sources` and `artifacts` of the
|
|
21
37
|
// corresponding source/context.
|
|
22
38
|
//
|
|
23
|
-
// Because different sources could define artifacts with the same absolute
|
|
24
|
-
// name, this compiler phase also put a property `messages` to the resulting
|
|
25
|
-
// model, which is a vector of messages for the redefinitions. (Using the same
|
|
26
|
-
// name for different definitions in one source is already recognized during
|
|
27
|
-
// parsing.)
|
|
28
|
-
//
|
|
29
39
|
// You get the compact "official" CSN format by applying the function exported
|
|
30
|
-
// by "../json/to-csn.js" to the
|
|
40
|
+
// by "../json/to-csn.js" to the XSN.
|
|
31
41
|
|
|
32
42
|
// Example 'file.cds':
|
|
33
43
|
// namespace A;
|
|
@@ -54,7 +64,7 @@
|
|
|
54
64
|
// An artifact definition looks as follows (example: context "A.B" above):
|
|
55
65
|
// {
|
|
56
66
|
// kind: 'context',
|
|
57
|
-
// name: { id: 'B', absolute: 'A.B', location: { <for the id "B"> } },
|
|
67
|
+
// name: { path: [ { id: 'B'} ], absolute: 'A.B', location: { <for the id "B"> } },
|
|
58
68
|
// artifacts: <for contexts, a dictionary of artifacts defined within>,
|
|
59
69
|
// location: { <of the complete artifact definition> } },
|
|
60
70
|
// _parent: <the parent artifact, here the source 'file.cds'>
|
|
@@ -74,11 +84,10 @@
|
|
|
74
84
|
// location: { <of the complete element definition> } },
|
|
75
85
|
// _parent: <the parent artifact, here the type "A.B.C">
|
|
76
86
|
// }
|
|
77
|
-
//
|
|
78
|
-
// './resolver.js'. We then get the properties `type.absolute` and `length`.
|
|
87
|
+
// --------- TODO: end in extra markdown document -------------------------------
|
|
79
88
|
|
|
80
89
|
// Sub phase 1 (addXYZ) - only for main artifacts
|
|
81
|
-
// - set _block links
|
|
90
|
+
// - set _block links for main definitions, vocabulary and extensions
|
|
82
91
|
// - store definitions (including context extensions), NO duplicate check
|
|
83
92
|
// - artifact name check
|
|
84
93
|
// - Note: the only allow name resolving is resolveUncheckedPath(),
|
|
@@ -96,6 +105,7 @@
|
|
|
96
105
|
// More sub phases...
|
|
97
106
|
|
|
98
107
|
// The main difficulty is the correct behavior concerning duplicate definitions
|
|
108
|
+
// - For code completion, all duplicate definitions must be further checked.
|
|
99
109
|
// - We need a unique object for the _subArtifacts dictionary.
|
|
100
110
|
// - We must have a property at the artifact whether there are duplicates in order
|
|
101
111
|
// to avoid consequential or repeated errors.
|
|
@@ -121,6 +131,7 @@ const {
|
|
|
121
131
|
dependsOnSilent,
|
|
122
132
|
pathName,
|
|
123
133
|
splitIntoPath,
|
|
134
|
+
annotationHasEllipsis,
|
|
124
135
|
} = require('./utils');
|
|
125
136
|
const { compareLayer } = require('./moduleLayers');
|
|
126
137
|
const { initBuiltins, isInReservedNamespace } = require('./builtins');
|
|
@@ -148,15 +159,15 @@ function define( model ) {
|
|
|
148
159
|
const {
|
|
149
160
|
resolveUncheckedPath,
|
|
150
161
|
checkAnnotate,
|
|
151
|
-
defineAnnotations,
|
|
152
162
|
} = model.$functions;
|
|
153
163
|
|
|
154
164
|
const extensionsDict = Object.create(null);
|
|
155
165
|
Object.assign( model.$functions, {
|
|
156
166
|
initArtifact,
|
|
157
167
|
initMembers,
|
|
158
|
-
extensionsDict, // a dictionary - TODO:
|
|
168
|
+
extensionsDict, // a dictionary - TODO: put directly into model?
|
|
159
169
|
checkDefinitions,
|
|
170
|
+
initAnnotations,
|
|
160
171
|
} );
|
|
161
172
|
// During the definer, we can only resolve artifact references, i.e,
|
|
162
173
|
// after a `.`, we only search in the `_subArtifacts` dictionary:
|
|
@@ -193,8 +204,9 @@ function define( model ) {
|
|
|
193
204
|
initNamespaceAndUsing( model.sources[name] );
|
|
194
205
|
dictForEach( model.definitions, initArtifact );
|
|
195
206
|
dictForEach( model.vocabularies, initVocabulary );
|
|
207
|
+
dictForEach( extensionsDict, initExtension );
|
|
196
208
|
|
|
197
|
-
mergeI18nBlocks(
|
|
209
|
+
mergeI18nBlocks();
|
|
198
210
|
}
|
|
199
211
|
|
|
200
212
|
// Phase 1: ----------------------------------------------------------------
|
|
@@ -213,9 +225,8 @@ function define( model ) {
|
|
|
213
225
|
let namespace = src.namespace && src.namespace.path;
|
|
214
226
|
let prefix = namespace ? `${ pathName( namespace ) }.` : '';
|
|
215
227
|
if (isInReservedNamespace(prefix)) {
|
|
216
|
-
error( 'reserved-namespace-cds', [ src.namespace.location, src.namespace ], {},
|
|
217
|
-
|
|
218
|
-
'The namespace "cds" is reserved for CDS builtins' );
|
|
228
|
+
error( 'reserved-namespace-cds', [ src.namespace.location, src.namespace ], { name: 'cds' },
|
|
229
|
+
'The namespace $(NAME) is reserved for CDS builtins' );
|
|
219
230
|
namespace = null;
|
|
220
231
|
}
|
|
221
232
|
if (src.$frontend !== 'json') { // CDL input
|
|
@@ -249,9 +260,8 @@ function define( model ) {
|
|
|
249
260
|
const { absolute } = art.name;
|
|
250
261
|
// TODO: check reserved, see checkName()/checkLocalizedObjects() of checks.js
|
|
251
262
|
if (absolute === 'cds' || isInReservedNamespace(absolute)) {
|
|
252
|
-
error( 'reserved-namespace-cds', [ art.name.location, art ], {},
|
|
253
|
-
|
|
254
|
-
'The namespace "cds" is reserved for CDS builtins' );
|
|
263
|
+
error( 'reserved-namespace-cds', [ art.name.location, art ], { name: 'cds' },
|
|
264
|
+
'The namespace $(NAME) is reserved for CDS builtins' );
|
|
255
265
|
const builtin = model.definitions[absolute];
|
|
256
266
|
if (builtin && builtin.builtin) // if already a builtin...
|
|
257
267
|
return;
|
|
@@ -259,8 +269,6 @@ function define( model ) {
|
|
|
259
269
|
}
|
|
260
270
|
else if (art.query && (absolute === 'localized' || absolute.startsWith( 'localized.' ))) {
|
|
261
271
|
// Due to recompilation, we don't emit this info message for JSON frontend.
|
|
262
|
-
// TODO: generalize this for $generated (definitions starting with
|
|
263
|
-
// "localized" just have `$generated: true` as default)
|
|
264
272
|
if (block.$frontend !== 'json') {
|
|
265
273
|
info( 'ignored-localized-definition', [ art.name.location, art ], {},
|
|
266
274
|
'This definition in the namespace "localized" is ignored' );
|
|
@@ -398,7 +406,7 @@ function define( model ) {
|
|
|
398
406
|
|
|
399
407
|
// Phase 2 ("init") --------------------------------------------------------
|
|
400
408
|
// Functions called from top-level: initNamespaceAndUsing(), initArtifact(),
|
|
401
|
-
// initVocabulary()
|
|
409
|
+
// initVocabulary(), initExtension()
|
|
402
410
|
|
|
403
411
|
function checkRedefinition( art ) {
|
|
404
412
|
if (!art.$duplicates || art.$errorReported === 'syntax-duplicate-extend' ||
|
|
@@ -419,6 +427,8 @@ function define( model ) {
|
|
|
419
427
|
}
|
|
420
428
|
|
|
421
429
|
function initNamespaceAndUsing( src ) {
|
|
430
|
+
if (src.$frontend && src.$frontend !== 'cdl')
|
|
431
|
+
return;
|
|
422
432
|
if (src.namespace) {
|
|
423
433
|
const decl = src.namespace;
|
|
424
434
|
const { path } = decl;
|
|
@@ -463,11 +473,11 @@ function define( model ) {
|
|
|
463
473
|
initParentLink( art, model.definitions );
|
|
464
474
|
const block = art._block;
|
|
465
475
|
checkRedefinition( art );
|
|
466
|
-
|
|
476
|
+
initAnnotations( art, block );
|
|
467
477
|
initMembers( art, art, block );
|
|
468
478
|
initDollarSelf( art ); // $self
|
|
469
479
|
if (art.params)
|
|
470
|
-
|
|
480
|
+
initDollarParameters( art );
|
|
471
481
|
if (art.includes && !(art.name.absolute in extensionsDict)) // TODO: in next phase?
|
|
472
482
|
extensionsDict[art.name.absolute] = []; // structure with includes must be "extended"
|
|
473
483
|
|
|
@@ -478,19 +488,23 @@ function define( model ) {
|
|
|
478
488
|
if (!setLink( art, '_leadingQuery', initQueryExpression( art.query, art ) ) )
|
|
479
489
|
return; // null or undefined in case of parse error
|
|
480
490
|
setLink( art._leadingQuery, '_$next', art );
|
|
481
|
-
// the following
|
|
491
|
+
// the following may be removed soon if we have:
|
|
482
492
|
// view elements as proxies to elements of leading query
|
|
483
493
|
if (art.elements) { // specified element via compilation of client-style CSN
|
|
484
494
|
setLink( art, 'elements$', art.elements );
|
|
485
495
|
delete art.elements;
|
|
486
496
|
}
|
|
497
|
+
if (art.enum) { // specified enum via compilation of client-style CSN
|
|
498
|
+
setLink( art, 'enum$', art.enum );
|
|
499
|
+
delete art.enum;
|
|
500
|
+
}
|
|
487
501
|
}
|
|
488
502
|
|
|
489
503
|
function initVocabulary( art ) {
|
|
490
504
|
initParentLink( art, model.vocabularies );
|
|
491
505
|
checkRedefinition( art );
|
|
492
506
|
const block = art._block;
|
|
493
|
-
|
|
507
|
+
initAnnotations( art, block );
|
|
494
508
|
initMembers( art, art, block );
|
|
495
509
|
}
|
|
496
510
|
|
|
@@ -516,6 +530,57 @@ function define( model ) {
|
|
|
516
530
|
parent._subArtifacts[absolute.substring( dot + 1 )] = art; // not dictAdd()
|
|
517
531
|
}
|
|
518
532
|
|
|
533
|
+
/** Initialize the extension `ext`.
|
|
534
|
+
*
|
|
535
|
+
* Currently:
|
|
536
|
+
*
|
|
537
|
+
* - initialize annotations (set _block, $priority, `...` check) on "main"
|
|
538
|
+
* extension and its columns do more later
|
|
539
|
+
* - for members in compile(): init annotations via extendMembers/annotateMembers
|
|
540
|
+
* - for members in parse.cdl(): init annotation via initMembers
|
|
541
|
+
*
|
|
542
|
+
* In the future:
|
|
543
|
+
*
|
|
544
|
+
* - also initialize members and member extensions/annotations here
|
|
545
|
+
* - we might also do other things, like calculating whether an `extend` is
|
|
546
|
+
* `annotate`-like, i.e. only contains name-resolution irrelevant extensions.
|
|
547
|
+
*/
|
|
548
|
+
function initExtension( ext ) {
|
|
549
|
+
const block = ext._block;
|
|
550
|
+
initAnnotations( ext, block, ext.kind );
|
|
551
|
+
if (ext.columns) // the columns themselves are "definitions"
|
|
552
|
+
ext.columns.forEach( col => initAnnotations( col, block ) );
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// Set _block links for annotations (necessary for layering) and do a late
|
|
556
|
+
// syntax check (`...` only with extensions, not definitions).
|
|
557
|
+
// extKind is either ext.kind (=art is extension) or false (=art is not an extension)
|
|
558
|
+
function initAnnotations( art, block, extKind = false ) {
|
|
559
|
+
// TODO: think of removing $priority, then
|
|
560
|
+
// no _block: define, _block: annotate/extend/edmx
|
|
561
|
+
// would fit with extending defs with props like length
|
|
562
|
+
for (const prop in art) {
|
|
563
|
+
if (prop.charAt(0) === '@') {
|
|
564
|
+
const anno = art[prop];
|
|
565
|
+
// TODO: make anno never be an array, see addAnnotation() in genericAntlrParser
|
|
566
|
+
if (Array.isArray( anno ))
|
|
567
|
+
anno.forEach( init );
|
|
568
|
+
else
|
|
569
|
+
init( anno );
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return;
|
|
573
|
+
|
|
574
|
+
function init( anno ) {
|
|
575
|
+
setLink( anno, '_block', block );
|
|
576
|
+
anno.$priority = extKind;
|
|
577
|
+
if (!extKind && annotationHasEllipsis( anno )) {
|
|
578
|
+
error( 'anno-unexpected-ellipsis',
|
|
579
|
+
[ anno.name.location, art ], { code: '...' } );
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
519
584
|
// From here til EOF, reexamine code ---------------------------------------
|
|
520
585
|
// See populate:
|
|
521
586
|
// - userQuery() or _query property?
|
|
@@ -541,7 +606,8 @@ function define( model ) {
|
|
|
541
606
|
setLink( art, '_$next', model.$magicVariables );
|
|
542
607
|
}
|
|
543
608
|
|
|
544
|
-
function
|
|
609
|
+
function initDollarParameters( art ) {
|
|
610
|
+
// TODO: remove $parameters in v4?
|
|
545
611
|
// TODO: use setMemberParent() ?
|
|
546
612
|
const parameters = {
|
|
547
613
|
name: { id: '$parameters', param: '$parameters', absolute: art.name.absolute },
|
|
@@ -604,16 +670,16 @@ function define( model ) {
|
|
|
604
670
|
// Either expression (value), expand or new association (target && type)
|
|
605
671
|
else if (col.value || col.expand || (col.target && col.type)) {
|
|
606
672
|
setLink( col, '_block', parent._block );
|
|
607
|
-
|
|
673
|
+
initAnnotations( col, parent._block );
|
|
608
674
|
if (col.inline) { // `@anno elem.{ * }` does not work
|
|
609
675
|
if (col.doc)
|
|
610
|
-
warning( 'syntax-anno
|
|
676
|
+
warning( 'syntax-ignoring-anno', [ col.doc.location, col ], { '#': 'doc' } );
|
|
611
677
|
|
|
612
678
|
// col.$annotations no available for CSN input, have to search.
|
|
613
679
|
// Warning about first annotation should be enough to avoid spam.
|
|
614
680
|
const firstAnno = Object.keys(col).find(key => key.startsWith('@'));
|
|
615
681
|
if (firstAnno)
|
|
616
|
-
warning( 'syntax-anno
|
|
682
|
+
warning( 'syntax-ignoring-anno', [ col[firstAnno].name.location, col ] );
|
|
617
683
|
}
|
|
618
684
|
// TODO: allow sub queries? at least in top-level expand without parallel ref
|
|
619
685
|
if (columns)
|
|
@@ -658,7 +724,7 @@ function define( model ) {
|
|
|
658
724
|
|
|
659
725
|
/**
|
|
660
726
|
* If we have a valid top-level exists, exists in filters of sub-expressions can be translated,
|
|
661
|
-
* since we will have a top-level subquery after exists-processing in the
|
|
727
|
+
* since we will have a top-level subquery after exists-processing in the forRelationalDB.
|
|
662
728
|
*
|
|
663
729
|
* Recursively drill down into:
|
|
664
730
|
* - the .path
|
|
@@ -886,17 +952,21 @@ function define( model ) {
|
|
|
886
952
|
/**
|
|
887
953
|
* Set property `_parent` for all elements in `parent` to `parent` and do so
|
|
888
954
|
* recursively for all sub elements.
|
|
955
|
+
*
|
|
956
|
+
* If not for extensions: construct === parent
|
|
889
957
|
*/
|
|
890
|
-
// If not for extensions: construct === parent
|
|
891
958
|
function initMembers( construct, parent, block, initExtensions = false ) {
|
|
892
959
|
// TODO: split extend from init
|
|
893
960
|
const isQueryExtension = kindProperties[construct.kind].isExtension &&
|
|
894
961
|
(parent._main || parent).query;
|
|
895
962
|
let obj = construct;
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
setLink(
|
|
963
|
+
let { items } = obj;
|
|
964
|
+
while (items) {
|
|
965
|
+
setLink( items, '_outer', obj );
|
|
966
|
+
setLink( items, '_parent', obj._parent );
|
|
967
|
+
setLink( items, '_block', block );
|
|
968
|
+
obj = items;
|
|
969
|
+
items = obj.items;
|
|
900
970
|
}
|
|
901
971
|
if (obj.target && targetIsTargetAspect( obj )) {
|
|
902
972
|
obj.targetAspect = obj.target;
|
|
@@ -913,7 +983,7 @@ function define( model ) {
|
|
|
913
983
|
if (obj.on && !obj.target) {
|
|
914
984
|
error( 'unexpected-on-for-composition', [ obj.on.location, construct ],
|
|
915
985
|
{},
|
|
916
|
-
'A managed aspect composition can\'t have a specified ON
|
|
986
|
+
'A managed aspect composition can\'t have a specified ON-condition' );
|
|
917
987
|
delete obj.on; // continuation semantics: not specified
|
|
918
988
|
}
|
|
919
989
|
if (targetAspect.elements) {
|
|
@@ -1017,9 +1087,9 @@ function define( model ) {
|
|
|
1017
1087
|
setMemberParent( elem, name, parent, construct !== parent && prop );
|
|
1018
1088
|
// console.log(message( null, elem.location, elem, {}, 'Info', 'INIT').toString())
|
|
1019
1089
|
checkRedefinition( elem );
|
|
1020
|
-
if (elem.kind === 'annotate')
|
|
1090
|
+
if (elem.kind === 'annotate' || elem.kind === 'extend')
|
|
1021
1091
|
checkAnnotate( elem, elem );
|
|
1022
|
-
|
|
1092
|
+
initAnnotations( elem, bl );
|
|
1023
1093
|
initMembers( elem, elem, bl, initExtensions );
|
|
1024
1094
|
|
|
1025
1095
|
// for a correct home path, setMemberParent needed to be called
|
|
@@ -1039,7 +1109,7 @@ function define( model ) {
|
|
|
1039
1109
|
std: 'Elements can\'t have a value',
|
|
1040
1110
|
entity: 'Entity elements can\'t have a value',
|
|
1041
1111
|
type: 'Type elements can\'t have a value',
|
|
1042
|
-
extend: '
|
|
1112
|
+
extend: 'Can\'t extend type/entity elements with values',
|
|
1043
1113
|
});
|
|
1044
1114
|
return;
|
|
1045
1115
|
}
|
|
@@ -1072,8 +1142,11 @@ function define( model ) {
|
|
|
1072
1142
|
'Actions and functions only exist top-level and for entities' );
|
|
1073
1143
|
}
|
|
1074
1144
|
else if (parent.kind === 'action' || parent.kind === 'function') {
|
|
1075
|
-
error( 'extend-action', [ construct.location, construct ], {},
|
|
1076
|
-
|
|
1145
|
+
error( 'extend-action', [ construct.location, construct ], { '#': parent.kind }, {
|
|
1146
|
+
std: 'Actions and functions can\'t be extended, only annotated',
|
|
1147
|
+
action: 'Actions can\'t be extended, only annotated',
|
|
1148
|
+
function: 'Functions can\'t be extended, only annotated',
|
|
1149
|
+
} );
|
|
1077
1150
|
}
|
|
1078
1151
|
else if (prop === 'params') {
|
|
1079
1152
|
if (!feature) {
|
|
@@ -1105,29 +1178,27 @@ function define( model ) {
|
|
|
1105
1178
|
}
|
|
1106
1179
|
return construct === parent;
|
|
1107
1180
|
}
|
|
1108
|
-
}
|
|
1109
1181
|
|
|
1110
|
-
/**
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
.filter(name => !!model.sources[name].i18n)
|
|
1118
|
-
.sort( (a, b) => compareLayer( model.sources[a], model.sources[b] ) );
|
|
1182
|
+
/**
|
|
1183
|
+
* Merge (optional) translations into the XSN model.
|
|
1184
|
+
*/
|
|
1185
|
+
function mergeI18nBlocks() {
|
|
1186
|
+
const sortedSources = Object.keys(model.sources)
|
|
1187
|
+
.filter(name => !!model.sources[name].i18n)
|
|
1188
|
+
.sort( (a, b) => compareLayer( model.sources[a], model.sources[b] ) );
|
|
1119
1189
|
|
|
1120
|
-
|
|
1121
|
-
|
|
1190
|
+
if (sortedSources.length === 0)
|
|
1191
|
+
return;
|
|
1122
1192
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1193
|
+
if (!model.i18n)
|
|
1194
|
+
model.i18n = Object.create( null );
|
|
1125
1195
|
|
|
1126
|
-
|
|
1127
|
-
|
|
1196
|
+
for (const name of sortedSources)
|
|
1197
|
+
initI18nFromSource( model.sources[name] );
|
|
1198
|
+
}
|
|
1128
1199
|
|
|
1129
1200
|
/**
|
|
1130
|
-
* Add the source's translations to the model. Warns if the
|
|
1201
|
+
* Add the source's translations to the model. Warns if the source's translations
|
|
1131
1202
|
* do not match the ones from previous sources.
|
|
1132
1203
|
*
|
|
1133
1204
|
* @param {XSN.SourceAst} src
|
|
@@ -1144,9 +1215,8 @@ function mergeI18nBlocks( model ) {
|
|
|
1144
1215
|
model.i18n[langKey][textKey] = sourceVal;
|
|
1145
1216
|
}
|
|
1146
1217
|
else if (modelVal.val !== sourceVal.val) {
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
{ prop: textKey, otherprop: langKey } );
|
|
1218
|
+
warning( 'i18n-different-value', sourceVal.location,
|
|
1219
|
+
{ prop: textKey, otherprop: langKey } );
|
|
1150
1220
|
}
|
|
1151
1221
|
}
|
|
1152
1222
|
}
|