@sap/cds-compiler 3.9.8 → 3.9.10
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 +10 -0
- package/lib/api/main.js +2 -2
- package/lib/base/message-registry.js +9 -1
- package/lib/compiler/resolve.js +4 -8
- package/lib/edm/annotations/genericTranslation.js +55 -54
- package/lib/transform/db/expansion.js +14 -5
- package/lib/transform/localized.js +16 -7
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,16 @@
|
|
|
7
7
|
Note: `beta` fixes, changes and features are usually not listed in this ChangeLog but [here](doc/CHANGELOG_BETA.md).
|
|
8
8
|
The compiler behavior concerning `beta` features can change at any time without notice.
|
|
9
9
|
|
|
10
|
+
## Version 3.9.10 - 2023-08-25
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- to.edm(x): Error reporting for incorrect handling of "Collection()" has been improved.
|
|
15
|
+
- to.sql/hdi/hdbcds: Views on views with parameters did not have localized convenience views based on
|
|
16
|
+
other localized views (missing `localized.` prefix in FROM clause)
|
|
17
|
+
- to.sql: Casting expressions to a structured type yields a proper error instead of strange compiler error.
|
|
18
|
+
- to.sql.migration: Don't drop-create views marked with `@cds.persistence.exists` or `@cds.persistence.skip`
|
|
19
|
+
|
|
10
20
|
## Version 3.9.8 - 2023-08-03
|
|
11
21
|
|
|
12
22
|
### Fixed
|
package/lib/api/main.js
CHANGED
|
@@ -375,8 +375,7 @@ function sqlMigration( csn, options, beforeImage ) {
|
|
|
375
375
|
const beforeArtifact = beforeImage.definitions[artifactName];
|
|
376
376
|
const diffArtifact = diff.definitions[artifactName];
|
|
377
377
|
// TODO: exists, abstract? isPersistedOnDb?
|
|
378
|
-
if (diffArtifact && diffArtifact['@cds.persistence.name'] &&
|
|
379
|
-
(diffArtifact.query || diffArtifact.projection) &&
|
|
378
|
+
if (diffArtifact && diffArtifact['@cds.persistence.name'] && csnUtils.isPersistedAsView(diffArtifact) &&
|
|
380
379
|
(diffArtifact[modelCompare.isChanged] === true || // we know it changed because we compared two views
|
|
381
380
|
diffArtifact[modelCompare.isChanged] === undefined)) { // if it was removed in the after, then we don't have the flag
|
|
382
381
|
drops.creates[artifactName] = `DROP VIEW ${ identifierUtils.renderArtifactName(artifactName) };`;
|
|
@@ -384,6 +383,7 @@ function sqlMigration( csn, options, beforeImage ) {
|
|
|
384
383
|
else if (diffArtifact &&
|
|
385
384
|
diffArtifact['@cds.persistence.skip'] !== true &&
|
|
386
385
|
diffArtifact.kind === beforeArtifact.kind && // detect action -> entity
|
|
386
|
+
csnUtils.isPersistedAsTable(diffArtifact) === csnUtils.isPersistedAsTable(beforeArtifact) && // detect removal of @cds.persistence.exists
|
|
387
387
|
csnUtils.isPersistedAsView(diffArtifact) === csnUtils.isPersistedAsView(beforeArtifact) // detect view -> entity
|
|
388
388
|
) { // don't render again, but need info for primary key extension
|
|
389
389
|
diffArtifact['@cds.persistence.skip'] = true;
|
|
@@ -742,6 +742,14 @@ const centralMessageTexts = {
|
|
|
742
742
|
entity: 'Entity $(ART) with managed compositions can\'t be used in types', // yet
|
|
743
743
|
},
|
|
744
744
|
|
|
745
|
+
'type-invalid-cast': {
|
|
746
|
+
std: 'Invalid cast to $(TYPE)', // unused
|
|
747
|
+
'to-structure': 'Can\'t cast to a structured type',
|
|
748
|
+
'from-structure': 'Structured elements can\'t be cast to a different type',
|
|
749
|
+
'expr-to-structure': 'Can\'t cast an expression to a structured type',
|
|
750
|
+
'val-to-structure': 'Can\'t cast $(VALUE) to a structured type'
|
|
751
|
+
},
|
|
752
|
+
|
|
745
753
|
// -----------------------------------------------------------------------------------
|
|
746
754
|
// Expressions
|
|
747
755
|
// -----------------------------------------------------------------------------------
|
|
@@ -849,7 +857,7 @@ const centralMessageTexts = {
|
|
|
849
857
|
// -----------------------------------------------------------------------------------
|
|
850
858
|
'enum': 'Value $(VALUE) is not one out of $(RAWVALUES) for $(ANNO) of type $(TYPE)',
|
|
851
859
|
'std': 'Unexpected value $(VALUE) for $(ANNO) of type $(TYPE)',
|
|
852
|
-
'
|
|
860
|
+
'incompval': 'Unexpected $(STR) value for $(ANNO) of type $(TYPE)',
|
|
853
861
|
'nestedcollection': 'Nested collections are not supported for $(ANNO)',
|
|
854
862
|
'enumincollection': 'Enum inside collection is not supported for $(ANNO)',
|
|
855
863
|
'multexpr': 'EDM JSON code contains more than one dynamic expression: $(RAWVALUES) for $(ANNO)',
|
package/lib/compiler/resolve.js
CHANGED
|
@@ -516,14 +516,10 @@ function resolve( model ) {
|
|
|
516
516
|
? art.value.args[0]?._artifact
|
|
517
517
|
: art.value._artifact;
|
|
518
518
|
if (elem && art.type) { // has explicit type
|
|
519
|
-
if (art.type._artifact?.elements)
|
|
520
|
-
error('type-cast
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
else if (elem.elements) { // TODO: calc elements
|
|
524
|
-
error('type-cast-structured', [ art.type.location, art ], {},
|
|
525
|
-
'Structured elements can\'t be cast to a different type');
|
|
526
|
-
}
|
|
519
|
+
if (art.type._artifact?.elements)
|
|
520
|
+
error( 'type-invalid-cast', [ art.type.location, art ], { '#': 'to-structure' } );
|
|
521
|
+
else if (elem.elements) // TODO: calc elements
|
|
522
|
+
error( 'type-invalid-cast', [ art.type.location, art ], { '#': 'from-structure' } );
|
|
527
523
|
}
|
|
528
524
|
}
|
|
529
525
|
|
|
@@ -921,30 +921,33 @@ function csn2annotationEdm(reqDefs, csnVocabularies, serviceName,
|
|
|
921
921
|
// cAnnoValue: the annotation value (c : csn)
|
|
922
922
|
// oTarget: the result object (o: odata)
|
|
923
923
|
// oTermName: current term
|
|
924
|
-
//
|
|
925
|
-
function handleValue(cAnnoValue, oTarget, oTermName,
|
|
924
|
+
// dTypeNameArg: expected type of cAnnoValue according to dictionary, may be null (d: dictionary)
|
|
925
|
+
function handleValue( cAnnoValue, oTarget, oTermName, dTypeNameArg, msg ) {
|
|
926
926
|
// this function basically only figures out what kind of annotation value we have
|
|
927
927
|
// (can be: array, expression, enum, pseudo-record, record, simple value),
|
|
928
928
|
// then calls a more specific function to deal with it and puts
|
|
929
929
|
// the result into the oTarget object
|
|
930
930
|
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
{
|
|
931
|
+
const [ dTypeName, dTypeIsACollection ] = stripCollection(dTypeNameArg);
|
|
932
|
+
|
|
933
|
+
if (Array.isArray(cAnnoValue)) {
|
|
934
|
+
if (isEnumType(dTypeName)) {
|
|
935
935
|
// if we find an array although we expect an enum, this may be a "flag enum"
|
|
936
|
-
checkMultiEnumValue(
|
|
936
|
+
checkMultiEnumValue();
|
|
937
937
|
oTarget.setJSON({ 'EnumMember': generateMultiEnumValue(cAnnoValue, false), 'EnumMember@odata.type' : '#'+dTypeName });
|
|
938
938
|
oTarget.setXml( { 'EnumMember': generateMultiEnumValue(cAnnoValue, true) });
|
|
939
939
|
}
|
|
940
|
-
else
|
|
941
|
-
|
|
942
|
-
oTarget.append(generateCollection(cAnnoValue, oTermName, dTypeName, msg));
|
|
940
|
+
else {
|
|
941
|
+
oTarget.append(generateCollection(cAnnoValue, oTermName, dTypeName, dTypeIsACollection, msg));
|
|
943
942
|
}
|
|
944
943
|
}
|
|
945
944
|
else if (cAnnoValue && typeof cAnnoValue === 'object') {
|
|
946
945
|
// an empty record is rendered as <Record/>
|
|
947
946
|
if ('=' in cAnnoValue) {
|
|
947
|
+
if (dTypeIsACollection) {
|
|
948
|
+
message('odata-anno-value', msg.location,
|
|
949
|
+
{ anno: msg.anno(), str: 'path', '#': 'incompval' });
|
|
950
|
+
}
|
|
948
951
|
// expression
|
|
949
952
|
const res = handleExpression(cAnnoValue['='], dTypeName);
|
|
950
953
|
oTarget.setXml( { [res.name] : res.value });
|
|
@@ -954,8 +957,8 @@ function csn2annotationEdm(reqDefs, csnVocabularies, serviceName,
|
|
|
954
957
|
const enumSymbol = cAnnoValue['#'];
|
|
955
958
|
// enum
|
|
956
959
|
if (dTypeName) {
|
|
957
|
-
const typeDef = getDictType(
|
|
958
|
-
if(typeDef && typeDef.$Allowed && !typeDef.Members) {
|
|
960
|
+
const typeDef = getDictType(dTypeName);
|
|
961
|
+
if (typeDef && typeDef.$Allowed && !typeDef.Members) {
|
|
959
962
|
const allowedValue = typeDef.$Allowed.Symbols[enumSymbol];
|
|
960
963
|
if(!allowedValue) {
|
|
961
964
|
message('odata-anno-value', msg.location,
|
|
@@ -982,7 +985,7 @@ function csn2annotationEdm(reqDefs, csnVocabularies, serviceName,
|
|
|
982
985
|
}
|
|
983
986
|
else if (cAnnoValue['$value'] !== undefined) {
|
|
984
987
|
// "pseudo-structure" used for annotating scalar annotations
|
|
985
|
-
handleValue(cAnnoValue
|
|
988
|
+
handleValue(cAnnoValue.$value, oTarget, oTermName, dTypeNameArg, msg);
|
|
986
989
|
|
|
987
990
|
const k = Object.keys(cAnnoValue).filter( x => x[0] === '@');
|
|
988
991
|
if (!k || k.length === 0) {
|
|
@@ -1005,7 +1008,11 @@ function csn2annotationEdm(reqDefs, csnVocabularies, serviceName,
|
|
|
1005
1008
|
}
|
|
1006
1009
|
else {
|
|
1007
1010
|
// regular record
|
|
1008
|
-
|
|
1011
|
+
if (dTypeIsACollection) {
|
|
1012
|
+
message('odata-anno-value', msg.location,
|
|
1013
|
+
{ anno: msg.anno(), str: 'structured', '#': 'incompval' });
|
|
1014
|
+
}
|
|
1015
|
+
oTarget.append(generateRecord(cAnnoValue, oTermName, dTypeName, dTypeIsACollection, msg));
|
|
1009
1016
|
}
|
|
1010
1017
|
}
|
|
1011
1018
|
else {
|
|
@@ -1021,7 +1028,6 @@ function csn2annotationEdm(reqDefs, csnVocabularies, serviceName,
|
|
|
1021
1028
|
}
|
|
1022
1029
|
oTarget.setJSON( { [res.jsonName] : res.value });
|
|
1023
1030
|
}
|
|
1024
|
-
|
|
1025
1031
|
// found an enum value ("#"), check whether this fits
|
|
1026
1032
|
// the expected type "dTypeName"
|
|
1027
1033
|
function checkEnumValue(value) {
|
|
@@ -1053,15 +1059,17 @@ function csn2annotationEdm(reqDefs, csnVocabularies, serviceName,
|
|
|
1053
1059
|
// cAnnoValue: array
|
|
1054
1060
|
// dTypeName: expected type, already identified as enum type
|
|
1055
1061
|
// array is expected to contain enum values
|
|
1056
|
-
function checkMultiEnumValue(
|
|
1057
|
-
|
|
1062
|
+
function checkMultiEnumValue( ) {
|
|
1063
|
+
// we know that dTypeName is not null
|
|
1058
1064
|
const type = getDictType(dTypeName);
|
|
1059
|
-
if (!type || type
|
|
1065
|
+
if (!type || type.IsFlags !== 'true') {
|
|
1060
1066
|
message('odata-anno-value', msg.location,
|
|
1061
|
-
{
|
|
1067
|
+
{
|
|
1068
|
+
anno: msg.anno(),
|
|
1062
1069
|
str: 'collection',
|
|
1063
1070
|
type: dTypeName,
|
|
1064
|
-
'#': '
|
|
1071
|
+
'#': 'incompval',
|
|
1072
|
+
});
|
|
1065
1073
|
}
|
|
1066
1074
|
|
|
1067
1075
|
let index = 0;
|
|
@@ -1092,8 +1100,6 @@ function csn2annotationEdm(reqDefs, csnVocabularies, serviceName,
|
|
|
1092
1100
|
}
|
|
1093
1101
|
}
|
|
1094
1102
|
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
1103
|
// found an expression value ("=") "expr"
|
|
1098
1104
|
// expected type is dTypeName
|
|
1099
1105
|
// note: expr can also be provided if an enum/complex type/collection is expected
|
|
@@ -1264,18 +1270,20 @@ function csn2annotationEdm(reqDefs, csnVocabularies, serviceName,
|
|
|
1264
1270
|
// dTypeName : name of the expected record type according to vocabulary, may be null
|
|
1265
1271
|
//
|
|
1266
1272
|
// can be called for a record directly below a term, or at a deeper level
|
|
1267
|
-
function generateRecord(obj, termName, dTypeName, msg) {
|
|
1273
|
+
function generateRecord( obj, termName, dTypeName, dTypeIsACollection, msg ) {
|
|
1268
1274
|
/** @type {object} */
|
|
1269
1275
|
const newRecord = new Edm.Record(v);
|
|
1270
1276
|
|
|
1271
1277
|
// first determine what is the actual type to be used for the record
|
|
1272
1278
|
if (dTypeName && !isComplexType(dTypeName)) {
|
|
1273
|
-
if (!getDictType(dTypeName) && !isPrimitiveType(dTypeName) && !
|
|
1274
|
-
message('odata-anno-dict', msg.location,
|
|
1275
|
-
|
|
1276
|
-
else
|
|
1279
|
+
if (!getDictType(dTypeName) && !isPrimitiveType(dTypeName) && !dTypeIsACollection) {
|
|
1280
|
+
message('odata-anno-dict', msg.location, { anno: msg.anno(), type: dTypeName });
|
|
1281
|
+
} else {
|
|
1277
1282
|
message('odata-anno-value', msg.location,
|
|
1278
|
-
|
|
1283
|
+
{
|
|
1284
|
+
anno: msg.anno(), str: 'structured', type: dTypeName, '#': 'incompval',
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1279
1287
|
return newRecord;
|
|
1280
1288
|
}
|
|
1281
1289
|
|
|
@@ -1383,19 +1391,14 @@ function csn2annotationEdm(reqDefs, csnVocabularies, serviceName,
|
|
|
1383
1391
|
|
|
1384
1392
|
// annoValue is an array
|
|
1385
1393
|
// dTypeName : Collection(...) according to dictionary
|
|
1386
|
-
function generateCollection(annoValue, termName, dTypeName, msg) {
|
|
1394
|
+
function generateCollection( annoValue, termName, dTypeName, dTypeIsACollection, msg ) {
|
|
1387
1395
|
const newCollection = new Edm.Collection(v);
|
|
1388
1396
|
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
}
|
|
1395
|
-
else {
|
|
1396
|
-
message('odata-anno-value', msg.location,
|
|
1397
|
-
{ anno: msg.anno(), str: 'collection', type: dTypeName, '#': 'struct' });
|
|
1398
|
-
}
|
|
1397
|
+
if (dTypeName && !dTypeIsACollection) {
|
|
1398
|
+
message('odata-anno-value', msg.location,
|
|
1399
|
+
{
|
|
1400
|
+
anno: msg.anno(), str: 'collection', type: dTypeName, '#': 'incompval',
|
|
1401
|
+
});
|
|
1399
1402
|
}
|
|
1400
1403
|
|
|
1401
1404
|
let index = 0;
|
|
@@ -1412,7 +1415,7 @@ function csn2annotationEdm(reqDefs, csnVocabularies, serviceName,
|
|
|
1412
1415
|
}
|
|
1413
1416
|
else if (value && typeof value === 'object') {
|
|
1414
1417
|
if (value['=']) {
|
|
1415
|
-
const res = handleExpression(value['='],
|
|
1418
|
+
const res = handleExpression(value['='], dTypeName);
|
|
1416
1419
|
const newPropertyPath = new Edm.ValueThing(v, res.name, res.value );
|
|
1417
1420
|
newPropertyPath.setJSON( { [res.name] : res.value } );
|
|
1418
1421
|
newCollection.append(newPropertyPath);
|
|
@@ -1425,13 +1428,13 @@ function csn2annotationEdm(reqDefs, csnVocabularies, serviceName,
|
|
|
1425
1428
|
newCollection.append(handleEdmJson(value['$edmJson'], msg));
|
|
1426
1429
|
}
|
|
1427
1430
|
else {
|
|
1428
|
-
newCollection.append(generateRecord(value, termName,
|
|
1431
|
+
newCollection.append(generateRecord(value, termName, dTypeName, dTypeIsACollection, msg));
|
|
1429
1432
|
}
|
|
1430
1433
|
}
|
|
1431
1434
|
else {
|
|
1432
|
-
const res = handleSimpleValue(value,
|
|
1433
|
-
const newThing = (value === null) ?new Edm.ValueThing(v, 'Null') : new Edm.ValueThing(v, res.name, value );
|
|
1434
|
-
newThing.setJSON( { [res.jsonName]
|
|
1435
|
+
const res = handleSimpleValue(value, dTypeName, msg);
|
|
1436
|
+
const newThing = (value === null) ? new Edm.ValueThing(v, 'Null') : new Edm.ValueThing(v, res.name, value );
|
|
1437
|
+
newThing.setJSON( { [res.jsonName]: res.value });
|
|
1435
1438
|
newCollection.append(newThing);
|
|
1436
1439
|
}
|
|
1437
1440
|
|
|
@@ -1783,23 +1786,21 @@ function csn2annotationEdm(reqDefs, csnVocabularies, serviceName,
|
|
|
1783
1786
|
return dTypeName;
|
|
1784
1787
|
}
|
|
1785
1788
|
|
|
1786
|
-
function stripCollection(typeName) {
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1789
|
+
function stripCollection( typeName ) {
|
|
1790
|
+
if (typeName) {
|
|
1791
|
+
const match = typeName.match(/^Collection\((.+)\)/);
|
|
1792
|
+
if (match)
|
|
1793
|
+
return [ match[1], true ];
|
|
1790
1794
|
}
|
|
1791
|
-
|
|
1795
|
+
|
|
1796
|
+
return [ typeName, false ];
|
|
1792
1797
|
}
|
|
1793
1798
|
|
|
1794
1799
|
function isPrimitiveType(typeName) {
|
|
1795
1800
|
return typeName.split('.')[0] === 'Edm';
|
|
1796
1801
|
}
|
|
1797
1802
|
|
|
1798
|
-
function
|
|
1799
|
-
return typeName.match(/^Collection\((.+)\)/) !== null;
|
|
1800
|
-
}
|
|
1801
|
-
|
|
1802
|
-
function isEnumType(dTypeName) {
|
|
1803
|
+
function isEnumType( dTypeName ) {
|
|
1803
1804
|
const type = getDictType(dTypeName);
|
|
1804
1805
|
return type && type['$kind'] === 'EnumType';
|
|
1805
1806
|
}
|
|
@@ -18,13 +18,11 @@ const { forEach } = require('../../utils/objectUtils');
|
|
|
18
18
|
* @param {CSN.Options} options
|
|
19
19
|
* @param {string} pathDelimiter
|
|
20
20
|
* @param {object} messageFunctions
|
|
21
|
-
* @param {Function} messageFunctions.error
|
|
22
|
-
* @param {Function} messageFunctions.info
|
|
23
|
-
* @param {Function} messageFunctions.throwWithAnyError
|
|
24
21
|
* @param {object} csnUtils
|
|
25
22
|
* @param {object} [iterateOptions]
|
|
26
23
|
*/
|
|
27
|
-
function expandStructureReferences( csn, options, pathDelimiter,
|
|
24
|
+
function expandStructureReferences( csn, options, pathDelimiter, messageFunctions, csnUtils, iterateOptions = {} ) {
|
|
25
|
+
const { error, info, throwWithAnyError } = messageFunctions;
|
|
28
26
|
const {
|
|
29
27
|
isStructured, get$combined, getFinalTypeInfo,
|
|
30
28
|
} = csnUtils;
|
|
@@ -32,7 +30,6 @@ function expandStructureReferences( csn, options, pathDelimiter, { error, info,
|
|
|
32
30
|
|
|
33
31
|
rewriteExpandInline();
|
|
34
32
|
|
|
35
|
-
|
|
36
33
|
applyTransformations(csn, {
|
|
37
34
|
keys: (parent, name, keys, path) => {
|
|
38
35
|
parent.keys = expand(keys, path.concat('keys'), true);
|
|
@@ -538,6 +535,18 @@ function expandStructureReferences( csn, options, pathDelimiter, { error, info,
|
|
|
538
535
|
col.as = implicitAs(col.ref);
|
|
539
536
|
newThing.push(col);
|
|
540
537
|
}
|
|
538
|
+
else if (col.cast?.type) {
|
|
539
|
+
// TODO: Support expanding `null as field : StructuredT`
|
|
540
|
+
const _art = col.cast._type || inspectRef(path.concat(i, 'cast', 'type')).art;
|
|
541
|
+
if (_art && isStructured(_art)) {
|
|
542
|
+
error('type-invalid-cast', path.concat(i, 'cast', 'type'), {
|
|
543
|
+
'#': col.val !== undefined ? 'val-to-structure' : 'expr-to-structure', value: col.val,
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
newThing.push(col);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
541
550
|
else {
|
|
542
551
|
newThing.push(col);
|
|
543
552
|
}
|
|
@@ -13,6 +13,7 @@ const {
|
|
|
13
13
|
forAllQueries,
|
|
14
14
|
sortCsnDefinitionsForTests,
|
|
15
15
|
} = require('../model/csnUtils');
|
|
16
|
+
const {CompilerAssertion} = require('../base/error');
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Indicator that a definition is localized and has a convenience view.
|
|
@@ -577,14 +578,22 @@ function _addLocalizationViews(csn, options, useJoins, config) {
|
|
|
577
578
|
if (!obj || !obj.ref)
|
|
578
579
|
return;
|
|
579
580
|
const ref = Array.isArray(obj.ref) ? obj.ref[0] : obj.ref;
|
|
580
|
-
if (typeof ref
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
else
|
|
581
|
+
if (typeof ref === 'string') {
|
|
582
|
+
const def = csn.definitions[ref];
|
|
583
|
+
if (def && def[_hasLocalizedView]) {
|
|
584
|
+
if (Array.isArray(obj.ref))
|
|
585
|
+
obj.ref[0] = def[_hasLocalizedView];
|
|
586
|
+
else
|
|
587
587
|
obj.ref = def[_hasLocalizedView];
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
} else if (ref.id) {
|
|
591
|
+
const def = csn.definitions[ref.id];
|
|
592
|
+
if (def && def[_hasLocalizedView])
|
|
593
|
+
obj.ref[0].id = def[_hasLocalizedView];
|
|
594
|
+
|
|
595
|
+
} else if (options.testMode) {
|
|
596
|
+
throw new CompilerAssertion('Debug me: Unhandled reference during localized-rewrite!');
|
|
588
597
|
}
|
|
589
598
|
}
|
|
590
599
|
|