@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.
- package/CHANGELOG.md +74 -0
- package/bin/cds_remove_invalid_whitespace.js +2 -1
- package/bin/cdsc.js +15 -11
- package/bin/cdshi.js +1 -0
- package/doc/CHANGELOG_BETA.md +7 -0
- package/lib/api/main.js +7 -19
- package/lib/api/options.js +5 -11
- package/lib/api/trace.js +0 -1
- package/lib/base/builtins.js +1 -0
- package/lib/base/location.js +4 -1
- package/lib/base/message-registry.js +29 -29
- package/lib/base/messages.js +22 -26
- package/lib/base/model.js +0 -2
- package/lib/base/node-helpers.js +0 -1
- package/lib/checks/enricher.js +1 -5
- package/lib/checks/structuredAnnoExpressions.js +30 -0
- package/lib/checks/validator.js +8 -0
- package/lib/compiler/assert-consistency.js +4 -1
- package/lib/compiler/base.js +1 -1
- package/lib/compiler/builtins.js +18 -2
- package/lib/compiler/checks.js +2 -5
- package/lib/compiler/define.js +7 -7
- package/lib/compiler/extend.js +68 -33
- package/lib/compiler/generate.js +1 -1
- package/lib/compiler/index.js +23 -6
- package/lib/compiler/lsp-api.js +501 -2
- package/lib/compiler/populate.js +2 -2
- package/lib/compiler/propagator.js +1 -4
- package/lib/compiler/resolve.js +2 -15
- package/lib/compiler/shared.js +112 -31
- package/lib/compiler/tweak-assocs.js +2 -16
- package/lib/compiler/utils.js +2 -1
- package/lib/compiler/xsn-model.js +4 -0
- package/lib/edm/annotations/genericTranslation.js +95 -42
- package/lib/edm/csn2edm.js +16 -4
- package/lib/edm/edm.js +2 -3
- package/lib/edm/edmAnnoPreprocessor.js +1 -2
- package/lib/edm/edmPreprocessor.js +1 -7
- package/lib/gen/Dictionary.json +29 -2
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +2 -1
- package/lib/gen/languageParser.js +4995 -4817
- package/lib/json/csnVersion.js +1 -1
- package/lib/json/from-csn.js +4 -7
- package/lib/json/to-csn.js +23 -12
- package/lib/language/antlrParser.js +2 -2
- package/lib/language/errorStrategy.js +0 -1
- package/lib/language/genericAntlrParser.js +35 -12
- package/lib/language/multiLineStringParser.js +3 -2
- package/lib/language/textUtils.js +1 -0
- package/lib/main.d.ts +28 -9
- package/lib/main.js +7 -4
- package/lib/model/csnRefs.js +20 -4
- package/lib/model/csnUtils.js +0 -2
- package/lib/model/revealInternalProperties.js +1 -1
- package/lib/modelCompare/compare.js +1 -1
- package/lib/optionProcessor.js +28 -9
- package/lib/render/manageConstraints.js +1 -1
- package/lib/render/toCdl.js +36 -7
- package/lib/render/toSql.js +1 -0
- package/lib/render/utils/common.js +12 -9
- package/lib/render/utils/stringEscapes.js +1 -0
- package/lib/transform/db/applyTransformations.js +13 -8
- package/lib/transform/db/associations.js +62 -54
- package/lib/transform/db/constraints.js +23 -25
- package/lib/transform/db/expansion.js +1 -6
- package/lib/transform/db/flattening.js +89 -111
- package/lib/transform/db/temporal.js +3 -4
- package/lib/transform/db/views.js +0 -1
- package/lib/transform/draft/odata.js +51 -3
- package/lib/transform/effective/annotations.js +3 -2
- package/lib/transform/effective/flattening.js +135 -0
- package/lib/transform/effective/main.js +6 -6
- package/lib/transform/effective/types.js +13 -9
- package/lib/transform/forOdata.js +0 -2
- package/lib/transform/forRelationalDB.js +0 -19
- package/lib/transform/localized.js +7 -8
- package/lib/transform/odata/flattening.js +39 -31
- package/lib/transform/odata/typesExposure.js +5 -17
- package/lib/transform/transformUtils.js +1 -1
- package/lib/transform/translateAssocsToJoins.js +21 -3
- package/lib/utils/file.js +13 -7
- package/lib/utils/moduleResolve.js +59 -8
- package/lib/utils/term.js +3 -2
- package/package.json +7 -3
- package/share/messages/message-explanations.json +2 -0
- package/share/messages/type-unexpected-foreign-keys.md +52 -0
- package/share/messages/type-unexpected-on-condition.md +52 -0
package/lib/base/messages.js
CHANGED
|
@@ -73,8 +73,8 @@ function isDowngradable( messageId, moduleName, options ) {
|
|
|
73
73
|
return false;
|
|
74
74
|
if (msg.severity !== 'Error')
|
|
75
75
|
return true;
|
|
76
|
-
//
|
|
77
|
-
if (msg.errorFor && msg.errorFor.includes('
|
|
76
|
+
// v6 messages are downgradable (except if errorFor also contains the current module).
|
|
77
|
+
if (msg.errorFor && msg.errorFor.includes('v6'))
|
|
78
78
|
return true;
|
|
79
79
|
const { configurableFor } = msg;
|
|
80
80
|
return (Array.isArray( configurableFor ))
|
|
@@ -91,9 +91,11 @@ function isDowngradable( messageId, moduleName, options ) {
|
|
|
91
91
|
function severityChangeMarker(msg, config) {
|
|
92
92
|
const severity = msg.severity || 'Error';
|
|
93
93
|
if (config.moduleForMarker) {
|
|
94
|
-
if (severity === 'Error' &&
|
|
94
|
+
if (severity === 'Error' &&
|
|
95
|
+
isDowngradable( msg.messageId, config.moduleForMarker,
|
|
96
|
+
{ deprecated: { downgradableErrors: true } }))
|
|
95
97
|
return '‹↓›';
|
|
96
|
-
if (msg.messageId && centralMessages[msg.messageId]?.errorFor?.includes('
|
|
98
|
+
if (msg.messageId && centralMessages[msg.messageId]?.errorFor?.includes('v6'))
|
|
97
99
|
return '‹↑›';
|
|
98
100
|
}
|
|
99
101
|
return '';
|
|
@@ -107,12 +109,16 @@ function severityChangeMarker(msg, config) {
|
|
|
107
109
|
class CompilationError extends Error {
|
|
108
110
|
/**
|
|
109
111
|
* @param {CompileMessage[]} messages
|
|
110
|
-
* @param {boolean} [dontSerializeMessages] If true, compiler messages are NOT part of the errors message text.
|
|
111
112
|
* @param {XSN.Model} [model] the XSN model, only to be set with options.attachValidNames
|
|
112
113
|
*/
|
|
113
|
-
constructor(messages, model
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
constructor(messages, model) {
|
|
115
|
+
// Because test frameworks such as mocha and jest to not call `toString()` on
|
|
116
|
+
// an unhandled CompilationError and instead use `e.stack` directly, there is
|
|
117
|
+
// no proper message about _what_ the root cause of the exception was.
|
|
118
|
+
// To mitigate that, we serialize the first error in the message as well.
|
|
119
|
+
const firstError = messages.find( m => m.severity === 'Error' )?.toString() || '';
|
|
120
|
+
super( `CDS compilation failed\n${firstError}` );
|
|
121
|
+
|
|
116
122
|
/** @since v4.0.0 */
|
|
117
123
|
this.code = 'ERR_CDS_COMPILATION_FAILURE';
|
|
118
124
|
this.messages = [ ...messages ].sort(compareMessageSeverityAware);
|
|
@@ -240,7 +246,7 @@ function reclassifiedSeverity( msg, options, moduleName ) {
|
|
|
240
246
|
if (errorFor.includes(moduleName))
|
|
241
247
|
return 'Error';
|
|
242
248
|
|
|
243
|
-
if (errorFor.includes('
|
|
249
|
+
if (errorFor.includes('v6') && isBetaEnabled(options, 'v6preview')) {
|
|
244
250
|
severity = 'Error';
|
|
245
251
|
if (!isDowngradable(msg.messageId, moduleName, options))
|
|
246
252
|
return severity;
|
|
@@ -555,8 +561,7 @@ function makeMessageFunction( model, options, moduleName = null ) {
|
|
|
555
561
|
|
|
556
562
|
function throwWithError() {
|
|
557
563
|
if (hasNewError) {
|
|
558
|
-
|
|
559
|
-
throw new CompilationError(messages, options.attachValidNames && model, dontSerializeMessages);
|
|
564
|
+
throw new CompilationError(messages, options.attachValidNames && model);
|
|
560
565
|
}
|
|
561
566
|
}
|
|
562
567
|
|
|
@@ -573,8 +578,7 @@ function makeMessageFunction( model, options, moduleName = null ) {
|
|
|
573
578
|
return;
|
|
574
579
|
const hasError = options.testMode ? hasNonDowngradableErrors : hasErrors;
|
|
575
580
|
if (hasError( messages, moduleName, options )) {
|
|
576
|
-
|
|
577
|
-
throw new CompilationError(messages, options.attachValidNames && model, dontSerializeMessages);
|
|
581
|
+
throw new CompilationError(messages, options.attachValidNames && model);
|
|
578
582
|
}
|
|
579
583
|
}
|
|
580
584
|
|
|
@@ -1018,10 +1022,6 @@ function replaceInString( text, params ) {
|
|
|
1018
1022
|
* @param {boolean} [config.noMessageId]
|
|
1019
1023
|
* If true, will _not_ show the message ID (+ explanation hint) in the output.
|
|
1020
1024
|
*
|
|
1021
|
-
* @param {boolean} [config.idInBrackets]
|
|
1022
|
-
* If true, the message ID (if there is one and noMessageId is falsey) will be put in brackets.
|
|
1023
|
-
* This will be the default in cds-compiler v5.
|
|
1024
|
-
*
|
|
1025
1025
|
* @param {boolean} [config.noHome]
|
|
1026
1026
|
* If true, will _not_ show message's semantic location.
|
|
1027
1027
|
*
|
|
@@ -1049,11 +1049,7 @@ function messageString( err, config ) {
|
|
|
1049
1049
|
const downgradable = severityChangeMarker(err, config);
|
|
1050
1050
|
// even with noHome, print err.home if the location is weak
|
|
1051
1051
|
const home = !err.home || config.noHome && err.$location?.endLine ? '' : ` (in ${ err.home })`;
|
|
1052
|
-
|
|
1053
|
-
let msgId = ''; // TODO(v5): Use brackets only
|
|
1054
|
-
if (err.messageId && !config.noMessageId)
|
|
1055
|
-
msgId = (config.idInBrackets) ? `[${err.messageId}]` : ` ${err.messageId}`;
|
|
1056
|
-
|
|
1052
|
+
const msgId = (err.messageId && !config.noMessageId) ? `[${err.messageId}]` : '';
|
|
1057
1053
|
return `${ location }${ severity }${ downgradable }${ msgId }: ${ err.message }${ home }`;
|
|
1058
1054
|
}
|
|
1059
1055
|
|
|
@@ -1065,7 +1061,7 @@ function messageString( err, config ) {
|
|
|
1065
1061
|
* @returns {string} can be used to uniquely identify a message
|
|
1066
1062
|
*/
|
|
1067
1063
|
function messageHash( msg ) {
|
|
1068
|
-
// parser messages do not provide semantic location, therefore we need to use the file location
|
|
1064
|
+
// parser messages do not provide semantic location, therefore$ we need to use the file location
|
|
1069
1065
|
if (!msg.home)
|
|
1070
1066
|
return messageString(msg);
|
|
1071
1067
|
const copy = { ...msg };
|
|
@@ -1118,7 +1114,7 @@ function messageHash( msg ) {
|
|
|
1118
1114
|
* If true/'always', ANSI escape codes will be used for coloring the severity. If false/'never',
|
|
1119
1115
|
* no coloring will be used. If 'auto', we will decide based on certain factors such
|
|
1120
1116
|
* as whether the shell is a TTY and whether the environment variable `NO_COLOR` is
|
|
1121
|
-
* unset.
|
|
1117
|
+
* unset or whether `FORCE_COLOR` is set.
|
|
1122
1118
|
*
|
|
1123
1119
|
* @returns {string}
|
|
1124
1120
|
*/
|
|
@@ -1285,7 +1281,7 @@ function _messageContext( err, config ) {
|
|
|
1285
1281
|
* @param {boolean | 'auto'} [config.color] If true, ANSI escape codes will be used for coloring the `^`. If false, no
|
|
1286
1282
|
* coloring will be used. If 'auto', we will decide based on certain factors such
|
|
1287
1283
|
* as whether the shell is a TTY and whether the environment variable 'NO_COLOR' is
|
|
1288
|
-
* unset.
|
|
1284
|
+
* unset or `FORCE_COLOR` is set.
|
|
1289
1285
|
* @returns {string}
|
|
1290
1286
|
*
|
|
1291
1287
|
* @deprecated Use `messageStringMultiline()` with `config.sourceMap` and `config.sourceLineMap` instead!
|
|
@@ -1353,7 +1349,7 @@ function compareMessageSeverityAware( a, b ) {
|
|
|
1353
1349
|
/**
|
|
1354
1350
|
* Return sort-relevant part of semantic location (after the ':').
|
|
1355
1351
|
* Messages without semantic locations are considered smaller (for syntax errors)
|
|
1356
|
-
* and (currently - should not happen in
|
|
1352
|
+
* and (currently - should not happen in v6) larger for other messages.
|
|
1357
1353
|
*
|
|
1358
1354
|
* @param {CompileMessage} msg
|
|
1359
1355
|
*/
|
package/lib/base/model.js
CHANGED
|
@@ -31,11 +31,9 @@ const availableBetaFlags = {
|
|
|
31
31
|
enableUniversalCsn: true,
|
|
32
32
|
odataTerms: true,
|
|
33
33
|
optionalActionFunctionParameters: true, // not supported by runtime, yet.
|
|
34
|
-
annotateForeignKeys: true,
|
|
35
34
|
effectiveCsn: true,
|
|
36
35
|
tenantVariable: true,
|
|
37
36
|
calcAssoc: true,
|
|
38
|
-
v5preview: true,
|
|
39
37
|
temporalRawProjection: true,
|
|
40
38
|
// disabled by --beta-mode
|
|
41
39
|
nestedServices: false,
|
package/lib/base/node-helpers.js
CHANGED
package/lib/checks/enricher.js
CHANGED
|
@@ -49,7 +49,6 @@ function enrichCsn( csn, options ) {
|
|
|
49
49
|
dictionary( csn, 'definitions', csn.definitions );
|
|
50
50
|
return { csn, cleanup };
|
|
51
51
|
|
|
52
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
53
52
|
function standard( parent, prop, node ) {
|
|
54
53
|
if (!node || typeof node !== 'object' || !{}.propertyIsEnumerable.call( parent, prop ))
|
|
55
54
|
return;
|
|
@@ -69,7 +68,7 @@ function enrichCsn( csn, options ) {
|
|
|
69
68
|
}
|
|
70
69
|
csnPath.pop();
|
|
71
70
|
}
|
|
72
|
-
|
|
71
|
+
|
|
73
72
|
function dictionary( node, prop, dict ) {
|
|
74
73
|
setProp(node, '$path', [ ...csnPath ]);
|
|
75
74
|
cleanupCallbacks.push(() => delete node.$path);
|
|
@@ -115,7 +114,6 @@ function enrichCsn( csn, options ) {
|
|
|
115
114
|
}
|
|
116
115
|
}
|
|
117
116
|
|
|
118
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
119
117
|
function columns( parent, prop, node ) {
|
|
120
118
|
// Establish the link relationships
|
|
121
119
|
parent[prop].forEach((column) => {
|
|
@@ -130,7 +128,6 @@ function enrichCsn( csn, options ) {
|
|
|
130
128
|
standard(parent, prop, node);
|
|
131
129
|
}
|
|
132
130
|
|
|
133
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
134
131
|
function simpleRef( node, prop, ref ) {
|
|
135
132
|
setProp(node, '$path', [ ...csnPath ]);
|
|
136
133
|
cleanupCallbacks.push(() => delete node.$path);
|
|
@@ -158,7 +155,6 @@ function enrichCsn( csn, options ) {
|
|
|
158
155
|
}
|
|
159
156
|
}
|
|
160
157
|
|
|
161
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
162
158
|
function pathRef( node, prop, path ) {
|
|
163
159
|
const {
|
|
164
160
|
links, art, scope, $env,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { isBuiltinType } = require('../base/builtins');
|
|
4
|
+
const { transformExpression, applyTransformationsOnNonDictionary } = require('../model/csnUtils');
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {object} member
|
|
8
|
+
*/
|
|
9
|
+
function checkAnnotationExpression( member, _memberName, _prop, path ) {
|
|
10
|
+
Object.keys(member).filter(pn => pn[0] === '@').forEach((anno) => {
|
|
11
|
+
applyTransformationsOnNonDictionary(member, anno, {
|
|
12
|
+
xpr: (parent, prop, _xpr, xprPath) => {
|
|
13
|
+
transformExpression(parent, prop, {
|
|
14
|
+
ref: (elemref, __prop, ref, refPath) => {
|
|
15
|
+
const { art, scope } = this.csnUtils.inspectRef(refPath);
|
|
16
|
+
if (scope !== '$magic' && art) {
|
|
17
|
+
const ft = this.csnUtils.getFinalTypeInfo(art.type);
|
|
18
|
+
if (!isBuiltinType(ft?.type))
|
|
19
|
+
this.error('odata-anno-xpr-ref', refPath, { anno, elemref, '#': 'flatten_builtin_type' });
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
}, xprPath);
|
|
23
|
+
},
|
|
24
|
+
}, {}, path);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
checkAnnotationExpression,
|
|
30
|
+
};
|
package/lib/checks/validator.js
CHANGED
|
@@ -15,6 +15,7 @@ const navigationIntoMany = require('./manyNavigations');
|
|
|
15
15
|
const checkUsedTypesForAnonymousAspectComposition = require('./managedInType');
|
|
16
16
|
const validateHasPersistedElements = require('./hasPersistedElements');
|
|
17
17
|
const checkForHanaTypes = require('./checkForTypes');
|
|
18
|
+
const { checkAnnotationExpression } = require('./structuredAnnoExpressions');
|
|
18
19
|
const checkForParams = require('./parameters');
|
|
19
20
|
// forOdata
|
|
20
21
|
const { validateDefaultValues } = require('./defaultValues');
|
|
@@ -210,6 +211,13 @@ function forRelationalDB( csn, that ) {
|
|
|
210
211
|
duplicate messages due to the forEachMemberRecursively.
|
|
211
212
|
TODO: check if this recursion can be factored out of the validator */
|
|
212
213
|
forEachMember(artifact, checkUsedTypesForAnonymousAspectComposition.bind(that));
|
|
214
|
+
},
|
|
215
|
+
(artifact, artifactName) => {
|
|
216
|
+
if (that.options.transformation === 'effective') {
|
|
217
|
+
forEachMemberRecursively(artifact, checkAnnotationExpression.bind(that), [ 'definitions', artifactName ], false, {
|
|
218
|
+
skipArtifact: a => a.returns || (a.params && !a.query),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
213
221
|
}
|
|
214
222
|
),
|
|
215
223
|
forRelationalDBQueryValidators.concat(commonQueryValidators),
|
|
@@ -208,6 +208,7 @@ function assertConsistency( model, stage ) {
|
|
|
208
208
|
'elements', '$autoElement', '$uncheckedElements', '_origin', '_extensions',
|
|
209
209
|
'$requireElementAccess', '_effectiveType', '$effectiveSeqNo', '_deps',
|
|
210
210
|
'$calcDepElement', '$filtered', '$enclosed', '_parent',
|
|
211
|
+
'deprecated', '$onlyInExprCtx',
|
|
211
212
|
],
|
|
212
213
|
schema: {
|
|
213
214
|
kind: { test: isString, enum: [ 'builtin' ] },
|
|
@@ -215,6 +216,8 @@ function assertConsistency( model, stage ) {
|
|
|
215
216
|
$autoElement: { test: isString },
|
|
216
217
|
$uncheckedElements: { test: isBoolean },
|
|
217
218
|
$requireElementAccess: { test: isBoolean },
|
|
219
|
+
deprecated: { test: isBoolean },
|
|
220
|
+
$onlyInExprCtx: { test: TODO },
|
|
218
221
|
// missing location for normal "elements"
|
|
219
222
|
elements: { test: TODO },
|
|
220
223
|
},
|
|
@@ -703,7 +706,7 @@ function assertConsistency( model, stage ) {
|
|
|
703
706
|
'localized', // e.g. compiler-generated elements for localized: `text` assoc, etc.
|
|
704
707
|
'localized-entity', // `.texts` entity
|
|
705
708
|
'localized-origin', // `.texts` entity
|
|
706
|
-
'nav', // only used for MASKED, TODO(
|
|
709
|
+
'nav', // only used for MASKED, TODO(v6): Remove
|
|
707
710
|
'none', // only used in ensureColumnName(): Used in object representing empty alias
|
|
708
711
|
'query', // inferred query properties, e.g. `key`
|
|
709
712
|
'rewrite', // on-conditions or FKeys are rewritten
|
package/lib/compiler/base.js
CHANGED
|
@@ -48,7 +48,7 @@ const kindProperties = {
|
|
|
48
48
|
normalized: 'action',
|
|
49
49
|
dict: 'actions',
|
|
50
50
|
}, // no extend params, only annotate
|
|
51
|
-
key: { normalized: 'element' },
|
|
51
|
+
key: { normalized: 'element', dict: 'elements' }, // dict for annotate
|
|
52
52
|
param: { elements: () => false, enum: () => false, dict: 'params' },
|
|
53
53
|
source: { artifacts: true }, // TODO -> $source
|
|
54
54
|
using: {},
|
package/lib/compiler/builtins.js
CHANGED
|
@@ -178,14 +178,15 @@ const magicVariables = {
|
|
|
178
178
|
// Allow shortcut in CDL: `$user` becomes `$user.id` in CSN.
|
|
179
179
|
$autoElement: 'id',
|
|
180
180
|
},
|
|
181
|
-
$at: {
|
|
181
|
+
$at: { // $at is considered deprecated since cds-compiler v5
|
|
182
182
|
elements: {
|
|
183
183
|
from: {}, to: {},
|
|
184
184
|
},
|
|
185
185
|
// Require that elements are accessed, i.e. no $at, only $at.<element>.
|
|
186
186
|
$requireElementAccess: true,
|
|
187
|
+
deprecated: true, // $at is deprecated; use $valid
|
|
187
188
|
},
|
|
188
|
-
$valid: {
|
|
189
|
+
$valid: {
|
|
189
190
|
elements: {
|
|
190
191
|
from: {}, to: {},
|
|
191
192
|
},
|
|
@@ -200,6 +201,15 @@ const magicVariables = {
|
|
|
200
201
|
$uncheckedElements: true,
|
|
201
202
|
$requireElementAccess: true,
|
|
202
203
|
},
|
|
204
|
+
$draft: {
|
|
205
|
+
elements: {
|
|
206
|
+
IsActiveEntity: {},
|
|
207
|
+
},
|
|
208
|
+
// Require that elements are accessed, i.e. no $draft, only $draft.<element>.
|
|
209
|
+
$requireElementAccess: true,
|
|
210
|
+
// See reference semantics in shared.js
|
|
211
|
+
$onlyInExprCtx: [ 'annotation', 'annoRewrite' ],
|
|
212
|
+
},
|
|
203
213
|
};
|
|
204
214
|
|
|
205
215
|
// see lib/render/renderUtil.js for DB-specific magic vars, specified in CAP CDS via function
|
|
@@ -437,6 +447,10 @@ function initBuiltins( model ) {
|
|
|
437
447
|
art.$uncheckedElements = magic.$uncheckedElements;
|
|
438
448
|
if (magic.$requireElementAccess)
|
|
439
449
|
art.$requireElementAccess = magic.$requireElementAccess;
|
|
450
|
+
if (magic.deprecated)
|
|
451
|
+
art.deprecated = magic.deprecated;
|
|
452
|
+
if (magic.$onlyInExprCtx)
|
|
453
|
+
art.$onlyInExprCtx = magic.$onlyInExprCtx;
|
|
440
454
|
|
|
441
455
|
createMagicElements( art, magic.elements );
|
|
442
456
|
if (options.variableReplacements?.[id])
|
|
@@ -461,6 +475,8 @@ function initBuiltins( model ) {
|
|
|
461
475
|
// Propagate this property so that it is available for sub-elements.
|
|
462
476
|
if (art.$uncheckedElements)
|
|
463
477
|
magic.$uncheckedElements = art.$uncheckedElements;
|
|
478
|
+
if (art.$onlyInExprCtx)
|
|
479
|
+
magic.$onlyInExprCtx = art.$onlyInExprCtx;
|
|
464
480
|
setProp( magic, '_parent', art );
|
|
465
481
|
// setProp( magic, '_effectiveType', magic );
|
|
466
482
|
if (elements[id] && typeof elements[id] === 'object')
|
package/lib/compiler/checks.js
CHANGED
|
@@ -54,9 +54,6 @@ function check( model ) {
|
|
|
54
54
|
function checkEvent( def ) {
|
|
55
55
|
// Ensure that events are structured. Up to compiler v4, we allowed non-structured events,
|
|
56
56
|
// because when we introduced them, it was not fully specified what they are.
|
|
57
|
-
// TODO(v5):
|
|
58
|
-
// - Make this a (configurable) error; move to acceptTypeOrElement
|
|
59
|
-
// - require type/elements to be set in parser
|
|
60
57
|
if (def.kind === 'event' && !def._effectiveType?.elements && !def._effectiveType?.projection)
|
|
61
58
|
message( 'def-expected-structured', [ (def.type || def.name).location, def ] );
|
|
62
59
|
}
|
|
@@ -862,8 +859,8 @@ function check( model ) {
|
|
|
862
859
|
// Tree-ish expression from the compiler (not augmented)
|
|
863
860
|
// eslint-disable-next-line max-len
|
|
864
861
|
return (isAssociationOperand( xpr.args[0] ) && isDollarSelfOrProjectionOperand( xpr.args[2] ) ||
|
|
865
|
-
|
|
866
|
-
|
|
862
|
+
// eslint-disable-next-line max-len
|
|
863
|
+
isAssociationOperand( xpr.args[2] ) && isDollarSelfOrProjectionOperand( xpr.args[0] ));
|
|
867
864
|
}
|
|
868
865
|
|
|
869
866
|
// Nothing else qualifies
|
package/lib/compiler/define.js
CHANGED
|
@@ -364,7 +364,7 @@ function define( model ) {
|
|
|
364
364
|
// must be called after addUsing().
|
|
365
365
|
function addNamespace( namespace, src ) {
|
|
366
366
|
// create using for own namespace:
|
|
367
|
-
// TODO: should we really do that in
|
|
367
|
+
// TODO: should we really do that (in v6)? See also initNamespaceAndUsing().
|
|
368
368
|
const last = namespace.path[namespace.path.length - 1];
|
|
369
369
|
const { id } = last;
|
|
370
370
|
if (src.artifacts[id] || last.id.includes( '.' ))
|
|
@@ -507,9 +507,10 @@ function define( model ) {
|
|
|
507
507
|
// TODO: message ids
|
|
508
508
|
function checkRedefinition( art ) {
|
|
509
509
|
if (!art.$duplicates || !art.name.id ||
|
|
510
|
-
art.$errorReported === 'syntax-duplicate-extend'
|
|
511
|
-
art.$errorReported === 'syntax-duplicate-annotate')
|
|
510
|
+
art.$errorReported === 'syntax-duplicate-extend')
|
|
512
511
|
return;
|
|
512
|
+
if (art.kind === 'annotate' || art.kind === 'extend')
|
|
513
|
+
return; // extensions are merged into a super-annotate; $duplicates are only kept for LSP
|
|
513
514
|
if (art._main) {
|
|
514
515
|
error( 'duplicate-definition', [ art.name.location, art ], {
|
|
515
516
|
name: art.name.id,
|
|
@@ -637,7 +638,6 @@ function define( model ) {
|
|
|
637
638
|
}
|
|
638
639
|
|
|
639
640
|
function initDollarParameters( art ) {
|
|
640
|
-
// TODO: remove $parameters in v5?
|
|
641
641
|
// TODO: use setMemberParent() ?
|
|
642
642
|
const parameters = {
|
|
643
643
|
name: { id: '$parameters' },
|
|
@@ -939,14 +939,14 @@ function define( model ) {
|
|
|
939
939
|
setLink( col, '_block', parent._block );
|
|
940
940
|
if (col.inline) { // `@anno elem.{ * }` does not work
|
|
941
941
|
if (col.doc) {
|
|
942
|
-
message( 'syntax-
|
|
942
|
+
message( 'syntax-unexpected-anno', [ col.doc.location, col ],
|
|
943
943
|
{ '#': 'doc', code: '.{ ‹inline› }' } );
|
|
944
944
|
}
|
|
945
945
|
// col.$annotations no available for CSN input, have to search.
|
|
946
946
|
// Message about first annotation should be enough to avoid spam.
|
|
947
947
|
const firstAnno = Object.keys( col ).find( key => key.startsWith( '@' ) );
|
|
948
948
|
if (firstAnno) {
|
|
949
|
-
message( 'syntax-
|
|
949
|
+
message( 'syntax-unexpected-anno', [ col[firstAnno].name.location, col ],
|
|
950
950
|
{ code: '.{ ‹inline› }' } );
|
|
951
951
|
}
|
|
952
952
|
}
|
|
@@ -1083,7 +1083,7 @@ function define( model ) {
|
|
|
1083
1083
|
hasElement = true; // warning with CDL input or `name: {}` in CSN input
|
|
1084
1084
|
}
|
|
1085
1085
|
if (hasElement) {
|
|
1086
|
-
// This message is similar to the one above. In
|
|
1086
|
+
// This message is similar to the one above. In v6, we could probably
|
|
1087
1087
|
// turn this warning into an error, remove `$syntax: 'element' (also in
|
|
1088
1088
|
// language.g4), and use the above `ext-unexpected-element` only for CSN input.
|
|
1089
1089
|
warning( 'ext-expecting-enum', [ obj.elements[$location], construct ],
|