@sap/cds-compiler 4.1.2 → 4.2.2
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 -1
- package/bin/cdsc.js +6 -3
- package/doc/CHANGELOG_BETA.md +5 -0
- package/doc/CHANGELOG_DEPRECATED.md +15 -0
- package/lib/api/main.js +2 -2
- package/lib/api/options.js +2 -2
- package/lib/api/validate.js +24 -24
- package/lib/base/message-registry.js +41 -6
- package/lib/base/messages.js +7 -0
- package/lib/base/model.js +37 -8
- package/lib/checks/elements.js +11 -10
- package/lib/checks/manyNavigations.js +33 -0
- package/lib/checks/onConditions.js +5 -2
- package/lib/checks/queryNoDbArtifacts.js +2 -3
- package/lib/checks/selectItems.js +4 -55
- package/lib/checks/utils.js +3 -2
- package/lib/checks/validator.js +3 -1
- package/lib/compiler/.eslintrc.json +2 -1
- package/lib/compiler/assert-consistency.js +27 -24
- package/lib/compiler/base.js +6 -2
- package/lib/compiler/builtins.js +34 -34
- package/lib/compiler/checks.js +179 -208
- package/lib/compiler/classes.js +2 -2
- package/lib/compiler/cycle-detector.js +6 -6
- package/lib/compiler/define.js +66 -45
- package/lib/compiler/extend.js +81 -72
- package/lib/compiler/finalize-parse-cdl.js +26 -26
- package/lib/compiler/generate.js +61 -45
- package/lib/compiler/index.js +47 -49
- package/lib/compiler/kick-start.js +8 -7
- package/lib/compiler/moduleLayers.js +1 -1
- package/lib/compiler/populate.js +42 -35
- package/lib/compiler/propagator.js +6 -6
- package/lib/compiler/resolve.js +170 -126
- package/lib/compiler/shared.js +122 -45
- package/lib/compiler/tweak-assocs.js +93 -40
- package/lib/compiler/utils.js +15 -12
- package/lib/edm/.eslintrc.json +40 -1
- package/lib/edm/annotations/genericTranslation.js +721 -707
- package/lib/edm/annotations/preprocessAnnotations.js +88 -77
- package/lib/edm/csn2edm.js +389 -378
- package/lib/edm/edm.js +678 -772
- package/lib/edm/edmAnnoPreprocessor.js +132 -146
- package/lib/edm/edmInboundChecks.js +29 -27
- package/lib/edm/edmPreprocessor.js +686 -646
- package/lib/edm/edmUtils.js +277 -296
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +1253 -1276
- package/lib/json/from-csn.js +34 -4
- package/lib/json/to-csn.js +4 -4
- package/lib/language/language.g4 +2 -5
- package/lib/main.d.ts +61 -1
- package/lib/model/csnUtils.js +31 -2
- package/lib/model/revealInternalProperties.js +1 -1
- package/lib/modelCompare/compare.js +37 -2
- package/lib/modelCompare/utils/filter.js +1 -1
- package/lib/optionProcessor.js +15 -3
- package/lib/render/toCdl.js +30 -4
- package/lib/render/toSql.js +5 -9
- package/lib/render/utils/common.js +8 -6
- package/lib/transform/db/applyTransformations.js +1 -1
- package/lib/transform/db/cdsPersistence.js +1 -1
- package/lib/transform/db/constraints.js +47 -17
- package/lib/transform/db/expansion.js +121 -47
- package/lib/transform/db/flattening.js +75 -7
- package/lib/transform/forOdata.js +4 -1
- package/lib/transform/forRelationalDB.js +80 -62
- package/lib/transform/localized.js +91 -54
- package/lib/transform/transformUtils.js +9 -10
- package/lib/utils/file.js +7 -7
- package/lib/utils/moduleResolve.js +210 -121
- package/lib/utils/objectUtils.js +1 -1
- package/package.json +5 -5
|
@@ -4,7 +4,7 @@ const { makeMessageFunction } = require('../../base/messages.js');
|
|
|
4
4
|
const { forEachDefinition, forEachGeneric } = require('../../model/csnUtils.js');
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
/** ************************************************************************************************
|
|
8
8
|
* preprocessAnnotations
|
|
9
9
|
*
|
|
10
10
|
* options:
|
|
@@ -14,9 +14,9 @@ const { forEachDefinition, forEachGeneric } = require('../../model/csnUtils.js')
|
|
|
14
14
|
* try to proceed with the processing as good as possible.
|
|
15
15
|
*
|
|
16
16
|
*/
|
|
17
|
-
function preprocessAnnotations(csn, serviceName, options) {
|
|
17
|
+
function preprocessAnnotations( csn, serviceName, options ) {
|
|
18
18
|
const { message } = makeMessageFunction(csn, options);
|
|
19
|
-
|
|
19
|
+
const fkSeparator = '_';
|
|
20
20
|
|
|
21
21
|
resolveShortcuts();
|
|
22
22
|
|
|
@@ -32,19 +32,20 @@ function preprocessAnnotations(csn, serviceName, options) {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// return value can be null is target has no key
|
|
35
|
-
function getKeyOfTargetOfManagedAssoc(anno, assoc) {
|
|
35
|
+
function getKeyOfTargetOfManagedAssoc( anno, assoc ) {
|
|
36
36
|
// assoc.target can be the name of the target or the object itself
|
|
37
37
|
const targetName = (typeof assoc.target === 'object') ? assoc.target.name : assoc.target;
|
|
38
|
-
const target
|
|
38
|
+
const target = (typeof assoc.target === 'object') ? assoc.target : csn.definitions[assoc.target];
|
|
39
39
|
|
|
40
40
|
const keyNames = Object.keys(target.elements).filter(x => target.elements[x].key && !target.elements[x].target);
|
|
41
41
|
if (keyNames.length === 0) {
|
|
42
42
|
keyNames.push('MISSING');
|
|
43
43
|
message('odata-anno-preproc', null, { anno, name: targetName, '#': 'nokey' },
|
|
44
|
-
|
|
44
|
+
'target $(NAME) has no key');
|
|
45
45
|
}
|
|
46
|
-
else if (keyNames.length > 1)
|
|
46
|
+
else if (keyNames.length > 1) {
|
|
47
47
|
message('odata-anno-preproc', null, { anno, name: targetName, '#': 'multkeys' });
|
|
48
|
+
}
|
|
48
49
|
|
|
49
50
|
return keyNames[0];
|
|
50
51
|
}
|
|
@@ -58,28 +59,33 @@ function preprocessAnnotations(csn, serviceName, options) {
|
|
|
58
59
|
function resolveShortcuts() {
|
|
59
60
|
forEachDefinition(csn, (artifact, artifactName) => {
|
|
60
61
|
const location = [ 'definitions', artifactName ];
|
|
61
|
-
if(artifactName === serviceName || artifactName.startsWith(serviceName
|
|
62
|
+
if (artifactName === serviceName || artifactName.startsWith(`${serviceName}.`)) {
|
|
62
63
|
handleAnnotations(artifactName, artifactName, artifact, location);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
artifact.params && Object.entries(artifact.params).forEach(([paramName, param]) => {
|
|
67
|
-
handleAnnotations(artifactName, paramName, param, [ ...location, 'actions', artifactName, 'params', paramName ]);
|
|
68
|
-
});
|
|
69
|
-
forEachGeneric(artifact, 'actions', (action, actionName) => {
|
|
70
|
-
action.params && Object.entries(action.params).forEach(([paramName, param]) => {
|
|
71
|
-
handleAnnotations(actionName, paramName, param, [ ...location, 'actions', actionName, 'params', paramName ]);
|
|
64
|
+
if (artifact.elements) {
|
|
65
|
+
Object.entries(artifact.elements).forEach(([ elementName, element ]) => {
|
|
66
|
+
handleAnnotations(artifactName, elementName, element, [ ...location, 'elements', elementName ]);
|
|
72
67
|
});
|
|
68
|
+
}
|
|
69
|
+
if (artifact.params) {
|
|
70
|
+
Object.entries(artifact.params).forEach(([ paramName, param ]) => {
|
|
71
|
+
handleAnnotations(artifactName, paramName, param, [ ...location, 'actions', artifactName, 'params', paramName ]);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
forEachGeneric(artifact, 'actions', (action, actionName) => {
|
|
75
|
+
if (action.params) {
|
|
76
|
+
Object.entries(action.params).forEach(([ paramName, param ]) => {
|
|
77
|
+
handleAnnotations(actionName, paramName, param, [ ...location, 'actions', actionName, 'params', paramName ]);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
73
80
|
});
|
|
74
81
|
}
|
|
75
82
|
});
|
|
76
83
|
|
|
77
|
-
function handleAnnotations(defName, carrierName, carrier, location) {
|
|
78
|
-
|
|
84
|
+
function handleAnnotations( defName, carrierName, carrier, location ) {
|
|
79
85
|
// collect the names of the carrier's annotation properties
|
|
80
|
-
const annoNames = Object.keys(carrier).filter( x => x[0] === '@')
|
|
86
|
+
const annoNames = Object.keys(carrier).filter( x => x[0] === '@');
|
|
81
87
|
|
|
82
|
-
annoNames.forEach(aName => {
|
|
88
|
+
annoNames.forEach((aName) => {
|
|
83
89
|
const aNameWithoutQualifier = aName.split('#')[0];
|
|
84
90
|
|
|
85
91
|
// Always - draft annotations, value is action name
|
|
@@ -97,45 +103,45 @@ function preprocessAnnotations(csn, serviceName, options) {
|
|
|
97
103
|
});
|
|
98
104
|
|
|
99
105
|
// inner functions
|
|
100
|
-
function draftAnnotations(aName, aNameWithoutQualifier) {
|
|
106
|
+
function draftAnnotations( aName, aNameWithoutQualifier ) {
|
|
101
107
|
if ((carrier.kind === 'entity') &&
|
|
102
108
|
(aNameWithoutQualifier === '@Common.DraftRoot.PreparationAction' ||
|
|
103
109
|
aNameWithoutQualifier === '@Common.DraftRoot.ActivationAction' ||
|
|
104
110
|
aNameWithoutQualifier === '@Common.DraftRoot.EditAction' ||
|
|
105
111
|
aNameWithoutQualifier === '@Common.DraftNode.PreparationAction')
|
|
106
|
-
|
|
112
|
+
) {
|
|
107
113
|
let value = carrier[aName];
|
|
108
114
|
// prefix with service name, if not already done
|
|
109
|
-
if (value === 'draftPrepare'
|
|
115
|
+
if (value === 'draftPrepare' || value === 'draftActivate' || value === 'draftEdit') {
|
|
110
116
|
// mocha test has no whatsMySchemaName
|
|
111
117
|
const schemaName = options.whatsMySchemaName && options.whatsMySchemaName(carrierName) || serviceName;
|
|
112
|
-
|
|
118
|
+
carrier[aName] = `${schemaName}.${value}`;
|
|
119
|
+
value = carrier[aName];
|
|
113
120
|
}
|
|
114
121
|
// for v2: function imports live inside EntityContainer -> path needs to contain "EntityContainer/"
|
|
115
122
|
// we decided to prefix names of bound action/functions with entity name -> needs to be reflected in path, too
|
|
116
123
|
if (isV2()) {
|
|
117
|
-
|
|
118
|
-
carrier[aName] = value.replace(/(draft(Prepare|Activate|Edit))$/, (match, p1) =>
|
|
124
|
+
const entityNameShort = carrierName.split('.').pop();
|
|
125
|
+
carrier[aName] = value.replace(/(draft(Prepare|Activate|Edit))$/, (match, p1) => `EntityContainer/${entityNameShort}_${p1}`);
|
|
119
126
|
}
|
|
120
127
|
}
|
|
121
128
|
}
|
|
122
129
|
|
|
123
|
-
function fixedValueListShortCut(anno) {
|
|
130
|
+
function fixedValueListShortCut( anno ) {
|
|
124
131
|
if (anno === '@Common.ValueList.entity' ||
|
|
125
132
|
anno === '@Common.ValueList.viaAssociation') {
|
|
126
|
-
|
|
127
133
|
const _fixedValueListShortCut = () => {
|
|
128
134
|
// note: we loop over all annotations that were originally present, even if they are
|
|
129
135
|
// removed from the carrier via this handler
|
|
130
136
|
// we don't remove anything from the array "annoNames"
|
|
131
137
|
|
|
132
138
|
// if CollectionPath is explicitly given, no shortcut expansion is made
|
|
133
|
-
if (carrier['@Common.ValueList.CollectionPath'])
|
|
139
|
+
if (carrier['@Common.ValueList.CollectionPath'])
|
|
134
140
|
return false;
|
|
135
|
-
|
|
141
|
+
|
|
136
142
|
|
|
137
143
|
if (carrier.kind === 'entity') {
|
|
138
|
-
message('odata-anno-preproc', [...location, anno], { anno, '#': 'notforentity' });
|
|
144
|
+
message('odata-anno-preproc', [ ...location, anno ], { anno, '#': 'notforentity' });
|
|
139
145
|
return false;
|
|
140
146
|
}
|
|
141
147
|
|
|
@@ -149,12 +155,12 @@ function preprocessAnnotations(csn, serviceName, options) {
|
|
|
149
155
|
// value is expected to be an expression, namely the path to an association of the carrier entity
|
|
150
156
|
const assocName = carrier['@Common.ValueList.viaAssociation']['='];
|
|
151
157
|
if (!assocName) {
|
|
152
|
-
message('odata-anno-preproc', [...location, anno], { anno, '#': 'viaassoc' });
|
|
158
|
+
message('odata-anno-preproc', [ ...location, anno ], { anno, '#': 'viaassoc' });
|
|
153
159
|
return false;
|
|
154
160
|
}
|
|
155
161
|
const assoc = csn.definitions[defName].elements[assocName];
|
|
156
162
|
if (!assoc || !assoc.target) {
|
|
157
|
-
message('odata-anno-preproc', [...location, anno], { anno, id: assocName, '#': 'noassoc' });
|
|
163
|
+
message('odata-anno-preproc', [ ...location, anno ], { anno, id: assocName, '#': 'noassoc' });
|
|
158
164
|
return false;
|
|
159
165
|
}
|
|
160
166
|
|
|
@@ -163,29 +169,31 @@ function preprocessAnnotations(csn, serviceName, options) {
|
|
|
163
169
|
}
|
|
164
170
|
else if (anno === '@Common.ValueList.entity') {
|
|
165
171
|
// if both annotations are present, ignore 'entity' and raise a message
|
|
166
|
-
if (annoNames.map(x=>x.split('#')[0]).find(x=>(x==='@Common.ValueList.viaAssociation'))) {
|
|
167
|
-
message('odata-anno-preproc', [...location, anno],
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
+
if (annoNames.map(x => x.split('#')[0]).find(x => (x === '@Common.ValueList.viaAssociation'))) {
|
|
173
|
+
message('odata-anno-preproc', [ ...location, anno ],
|
|
174
|
+
{
|
|
175
|
+
name: '@Common.ValueList.entity',
|
|
176
|
+
anno: '@Common.ValueList',
|
|
177
|
+
value: 'entity',
|
|
178
|
+
code: 'viaAssociation',
|
|
179
|
+
'#': 'vallistignored',
|
|
180
|
+
});
|
|
172
181
|
return false;
|
|
173
182
|
}
|
|
174
183
|
|
|
175
184
|
const annoVal = carrier['@Common.ValueList.entity']; // name of value list entity
|
|
176
|
-
if (annoVal['='])
|
|
177
|
-
message('odata-anno-preproc', [...location, anno], { anno, '#': 'notastring' }
|
|
178
|
-
|
|
179
|
-
}
|
|
185
|
+
if (annoVal['='])
|
|
186
|
+
message('odata-anno-preproc', [ ...location, anno ], { anno, '#': 'notastring' });
|
|
187
|
+
|
|
180
188
|
// mocha test has no whatsMySchemaName
|
|
181
|
-
const schemaName = options.whatsMySchemaName && options.whatsMySchemaName(defName) || serviceName
|
|
189
|
+
const schemaName = options.whatsMySchemaName && options.whatsMySchemaName(defName) || serviceName;
|
|
182
190
|
enameShort = annoVal['='] || annoVal;
|
|
183
|
-
enameFull = schemaName
|
|
191
|
+
enameFull = `${schemaName}.${enameShort}`;
|
|
184
192
|
}
|
|
185
193
|
|
|
186
194
|
const vlEntity = csn.definitions[enameFull]; // (object) value list entity
|
|
187
195
|
if (!vlEntity) {
|
|
188
|
-
message('odata-anno-preproc', [...location, anno ], { anno, id: enameFull, '#': 'notexist' });
|
|
196
|
+
message('odata-anno-preproc', [ ...location, anno ], { anno, id: enameFull, '#': 'notexist' });
|
|
189
197
|
return false;
|
|
190
198
|
}
|
|
191
199
|
|
|
@@ -205,11 +213,10 @@ function preprocessAnnotations(csn, serviceName, options) {
|
|
|
205
213
|
|
|
206
214
|
// if this carrier is a generated foreign key field and the association is marked @cds.api.ignore
|
|
207
215
|
// rename the localDataProp to be 'assocName/key'
|
|
208
|
-
if(carrier['@cds.api.ignore']) {
|
|
216
|
+
if (carrier['@cds.api.ignore']) {
|
|
209
217
|
const assocName = carrier['@odata.foreignKey4'];
|
|
210
|
-
if(assocName && options.isV4())
|
|
211
|
-
localDataProp = localDataProp.replace(assocName+fkSeparator, assocName
|
|
212
|
-
}
|
|
218
|
+
if (assocName && options.isV4())
|
|
219
|
+
localDataProp = localDataProp.replace(assocName + fkSeparator, `${assocName}/`);
|
|
213
220
|
}
|
|
214
221
|
|
|
215
222
|
// valueListProp: the (single) key field of the value list entity
|
|
@@ -217,11 +224,12 @@ function preprocessAnnotations(csn, serviceName, options) {
|
|
|
217
224
|
let valueListProp = null;
|
|
218
225
|
const keys = Object.keys(vlEntity.elements).filter( x => vlEntity.elements[x].key && !vlEntity.elements[x].target );
|
|
219
226
|
if (keys.length === 0) {
|
|
220
|
-
message('odata-anno-preproc', [...location, anno], { anno, name: enameFull, '#': 'vhlnokey' });
|
|
227
|
+
message('odata-anno-preproc', [ ...location, anno ], { anno, name: enameFull, '#': 'vhlnokey' });
|
|
221
228
|
return false;
|
|
222
229
|
}
|
|
223
|
-
else if (keys.length > 1)
|
|
224
|
-
message('odata-anno-preproc', [...location, anno], { anno, name: enameFull, '#': 'vhlmultkeys' });
|
|
230
|
+
else if (keys.length > 1) {
|
|
231
|
+
message('odata-anno-preproc', [ ...location, anno ], { anno, name: enameFull, '#': 'vhlmultkeys' });
|
|
232
|
+
}
|
|
225
233
|
valueListProp = keys[0];
|
|
226
234
|
|
|
227
235
|
// textField:
|
|
@@ -234,11 +242,14 @@ function preprocessAnnotations(csn, serviceName, options) {
|
|
|
234
242
|
const Identification = vlEntity['@UI.Identification'];
|
|
235
243
|
if (Identification && Identification[0] && Identification[0]['=']) {
|
|
236
244
|
textField = Identification[0]['='];
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
|
|
245
|
+
}
|
|
246
|
+
else if (Identification && Identification[0] && Identification[0].Value && Identification[0].Value['=']) {
|
|
247
|
+
textField = Identification[0].Value['='];
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
240
250
|
const stringFields = Object.keys(vlEntity.elements).filter(
|
|
241
|
-
x => !vlEntity.elements[x].key && vlEntity.elements[x].type === 'cds.String'
|
|
251
|
+
x => !vlEntity.elements[x].key && vlEntity.elements[x].type === 'cds.String'
|
|
252
|
+
);
|
|
242
253
|
if (stringFields.length === 1)
|
|
243
254
|
textField = stringFields[0];
|
|
244
255
|
}
|
|
@@ -246,21 +257,21 @@ function preprocessAnnotations(csn, serviceName, options) {
|
|
|
246
257
|
// explicitly provided parameters win
|
|
247
258
|
let parameters = carrier['@Common.ValueList.Parameters'];
|
|
248
259
|
if (!parameters) {
|
|
249
|
-
parameters = [{
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}];
|
|
260
|
+
parameters = [ {
|
|
261
|
+
$Type: 'Common.ValueListParameterInOut',
|
|
262
|
+
LocalDataProperty: { '=': localDataProp },
|
|
263
|
+
ValueListProperty: valueListProp,
|
|
264
|
+
} ];
|
|
254
265
|
if (textField) {
|
|
255
266
|
parameters[1] = {
|
|
256
|
-
|
|
257
|
-
|
|
267
|
+
$Type: 'Common.ValueListParameterDisplayOnly',
|
|
268
|
+
ValueListProperty: textField,
|
|
258
269
|
};
|
|
259
270
|
}
|
|
260
271
|
}
|
|
261
272
|
|
|
262
273
|
const newObj = Object.create( Object.getPrototypeOf(carrier) );
|
|
263
|
-
Object.keys(carrier).forEach( e => {
|
|
274
|
+
Object.keys(carrier).forEach( (e) => {
|
|
264
275
|
if (e === '@Common.ValueList.entity' || e === '@Common.ValueList.viaAssociation') {
|
|
265
276
|
newObj['@Common.ValueList.Label'] = label;
|
|
266
277
|
newObj['@Common.ValueList.CollectionPath'] = enameShort;
|
|
@@ -278,7 +289,7 @@ function preprocessAnnotations(csn, serviceName, options) {
|
|
|
278
289
|
});
|
|
279
290
|
Object.assign(carrier, newObj);
|
|
280
291
|
return true;
|
|
281
|
-
}
|
|
292
|
+
};
|
|
282
293
|
|
|
283
294
|
const success = _fixedValueListShortCut();
|
|
284
295
|
if (!success) {
|
|
@@ -289,23 +300,23 @@ function preprocessAnnotations(csn, serviceName, options) {
|
|
|
289
300
|
}
|
|
290
301
|
}
|
|
291
302
|
|
|
292
|
-
function textArrangementReordering(aName, aNameWithoutQualifier) {
|
|
303
|
+
function textArrangementReordering( aName, aNameWithoutQualifier ) {
|
|
293
304
|
if (aNameWithoutQualifier === '@Common.TextArrangement') {
|
|
294
|
-
|
|
295
|
-
|
|
305
|
+
const value = carrier[aName];
|
|
306
|
+
const textAnno = carrier['@Common.Text'];
|
|
296
307
|
// can only occur if there is a @Common.Text annotation at the same target
|
|
297
|
-
if (!textAnno)
|
|
298
|
-
message('odata-anno-preproc', [...location, '@Common.TextArrangement'], { anno: '@Common.TextArrangement', name: '@Common.Text', '#': 'txtarr' });
|
|
299
|
-
}
|
|
308
|
+
if (!textAnno)
|
|
309
|
+
message('odata-anno-preproc', [ ...location, '@Common.TextArrangement' ], { anno: '@Common.TextArrangement', name: '@Common.Text', '#': 'txtarr' });
|
|
300
310
|
|
|
301
|
-
|
|
311
|
+
|
|
312
|
+
// change the scalar anno into a "pseudo-structured" one
|
|
302
313
|
// TODO should be flattened, but then alphabetical order is destroyed
|
|
303
314
|
|
|
304
315
|
// Do not overwrite existing nested annotation values, instead give existing
|
|
305
316
|
// nested annotation precedence and remove outer annotation (always)
|
|
306
|
-
if(!carrier['@Common.Text.@UI.TextArrangement'] && textAnno)
|
|
307
|
-
carrier['@Common.Text'] = {
|
|
308
|
-
|
|
317
|
+
if (!carrier['@Common.Text.@UI.TextArrangement'] && textAnno)
|
|
318
|
+
carrier['@Common.Text'] = { $value: textAnno, '@UI.TextArrangement': value };
|
|
319
|
+
|
|
309
320
|
delete carrier[aName];
|
|
310
321
|
}
|
|
311
322
|
}
|