@sap/cds-compiler 4.0.2 → 4.1.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 +100 -5
- package/bin/cdsc.js +12 -12
- package/doc/CHANGELOG_BETA.md +11 -0
- package/lib/api/main.js +31 -11
- package/lib/api/validate.js +1 -1
- package/lib/base/location.js +6 -7
- package/lib/base/message-registry.js +84 -38
- package/lib/base/messages.js +11 -10
- package/lib/base/model.js +6 -2
- package/lib/checks/defaultValues.js +6 -6
- package/lib/checks/foreignKeys.js +0 -5
- package/lib/checks/onConditions.js +17 -12
- package/lib/checks/queryNoDbArtifacts.js +132 -72
- package/lib/checks/sql-snippets.js +15 -4
- package/lib/checks/types.js +3 -3
- package/lib/checks/utils.js +1 -1
- package/lib/compiler/assert-consistency.js +44 -16
- package/lib/compiler/base.js +1 -0
- package/lib/compiler/builtins.js +7 -8
- package/lib/compiler/checks.js +274 -197
- package/lib/compiler/classes.js +62 -0
- package/lib/compiler/cycle-detector.js +3 -3
- package/lib/compiler/define.js +63 -50
- package/lib/compiler/extend.js +38 -20
- package/lib/compiler/finalize-parse-cdl.js +2 -1
- package/lib/compiler/generate.js +0 -8
- package/lib/compiler/index.js +9 -7
- package/lib/compiler/kick-start.js +2 -0
- package/lib/compiler/populate.js +139 -110
- package/lib/compiler/propagator.js +4 -3
- package/lib/compiler/resolve.js +157 -126
- package/lib/compiler/shared.js +706 -404
- package/lib/compiler/tweak-assocs.js +21 -10
- package/lib/compiler/utils.js +228 -36
- package/lib/edm/annotations/genericTranslation.js +1 -1
- package/lib/edm/edm.js +4 -1
- package/lib/edm/edmPreprocessor.js +5 -4
- package/lib/edm/edmUtils.js +2 -4
- package/lib/gen/Dictionary.json +34 -10
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +3987 -3963
- package/lib/json/from-csn.js +43 -47
- package/lib/json/to-csn.js +11 -11
- package/lib/language/antlrParser.js +2 -1
- package/lib/language/genericAntlrParser.js +52 -43
- package/lib/language/language.g4 +59 -59
- package/lib/language/multiLineStringParser.js +2 -0
- package/lib/main.d.ts +5 -0
- package/lib/model/csnRefs.js +37 -19
- package/lib/model/csnUtils.js +20 -16
- package/lib/model/revealInternalProperties.js +29 -21
- package/lib/modelCompare/compare.js +112 -39
- package/lib/modelCompare/utils/filter.js +54 -24
- package/lib/optionProcessor.js +6 -6
- package/lib/render/manageConstraints.js +20 -17
- package/lib/render/toCdl.js +34 -20
- package/lib/render/toHdbcds.js +2 -2
- package/lib/render/toRename.js +4 -9
- package/lib/render/toSql.js +77 -26
- package/lib/render/utils/common.js +3 -3
- package/lib/render/utils/unique.js +52 -0
- package/lib/transform/db/applyTransformations.js +61 -20
- package/lib/transform/db/assertUnique.js +7 -8
- package/lib/transform/db/associations.js +2 -2
- package/lib/transform/db/cdsPersistence.js +8 -8
- package/lib/transform/db/expansion.js +17 -21
- package/lib/transform/db/flattening.js +23 -23
- package/lib/transform/db/rewriteCalculatedElements.js +20 -14
- package/lib/transform/db/temporal.js +1 -1
- package/lib/transform/db/transformExists.js +8 -7
- package/lib/transform/db/views.js +73 -33
- package/lib/transform/draft/db.js +11 -9
- package/lib/transform/draft/odata.js +1 -1
- package/lib/transform/{forOdataNew.js → forOdata.js} +6 -6
- package/lib/transform/forRelationalDB.js +69 -75
- package/lib/transform/localized.js +6 -5
- package/lib/transform/odata/toFinalBaseType.js +3 -3
- package/lib/transform/{transformUtilsNew.js → transformUtils.js} +4 -101
- package/lib/transform/translateAssocsToJoins.js +14 -28
- package/package.json +1 -1
- package/share/messages/check-proper-type-of.md +1 -1
- package/share/messages/{check-proper-type.md → def-missing-type.md} +3 -5
- package/share/messages/message-explanations.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,74 @@
|
|
|
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 4.1.2 - 2023-07-31
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- to.hdi.migration: Changes in constraints are not rendered as part of the .hdbmigrationtable file, as they belong in other HDI artifacts
|
|
15
|
+
|
|
16
|
+
## Version 4.1.0 - 2023-07-28
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Calculated elements "on-read" can now reference localized elements.
|
|
21
|
+
- Aliases for columns inside sub-queries are now optional, also for expressions.
|
|
22
|
+
- for.odata/to.hdi/to.sql: Specified default value on a managed association is forwarded to a foreign key
|
|
23
|
+
if association has exactly one foreign key.
|
|
24
|
+
- CDL: Annotation-only aspects having no `elements` and `actions` can now be defined with
|
|
25
|
+
the CDL syntax `@Anno… aspect Name;`. They cannot be extended with elements or actions
|
|
26
|
+
in order to ensure that they can always be used to extend non-structures.
|
|
27
|
+
To allow the former but not the latter, use `@Anno… aspect Name {…};`.
|
|
28
|
+
- to.sql: Support session variables for h2
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- api: Function `isInReservedNamespace(name)` handles name `cds` as being in a reserved namespace as well.
|
|
33
|
+
- `CompilationError.messages` are now sorted severity aware. Errors are listed first.
|
|
34
|
+
- Compiler:
|
|
35
|
+
+ Improve the calculation of semantic code completion candidates.
|
|
36
|
+
+ Some checks, like those for valid `on` conditions of associations,
|
|
37
|
+
are now already done with `compile` and not just the backends.
|
|
38
|
+
+ SQL `cast()`s must always have a `type` property
|
|
39
|
+
+ Type properties such as `precision` or `length` must be accompanied by a type (possibly inferred).
|
|
40
|
+
- for.odata/to.hdi/to.sql: No longer reject unmanaged associations as foreign keys of a managed association.
|
|
41
|
+
Instead, ignore such references during ON-condition rewriting and foreign key generation. Referring to
|
|
42
|
+
unmanaged associations is incompatible with SAP HANA CDS naming mode 'hdbcds'.
|
|
43
|
+
- to.sql: Rework session variables for postgres.
|
|
44
|
+
- Update OData vocabularies: 'Common', 'HTML5', 'PersonalData', 'UI'.
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
|
|
48
|
+
- Compiler:
|
|
49
|
+
+ ensure that annotations of elements in anonymous aspects of managed compositions
|
|
50
|
+
are not lost.
|
|
51
|
+
+ issue error for definitions like `entity Self as projection on Base { $self.* };`
|
|
52
|
+
instead of simply concluding that the projection has zero elements.
|
|
53
|
+
+ do not report a invalid cyclic dependency if associations between two entities
|
|
54
|
+
are valid cycles.
|
|
55
|
+
+ Element type references can again follow associations (removed v4.0 incompatibility).
|
|
56
|
+
- to.sql:
|
|
57
|
+
+ `$self` references inside a nested projection using `$self` was incorrectly resolved.
|
|
58
|
+
+ associations to entities marked with `@cds.persistence.skip` were not properly
|
|
59
|
+
checked inside nested projections.
|
|
60
|
+
+ Select items casting `null` to an arrayed type work again, e.g. `null as ManyType`.
|
|
61
|
+
- to.sql/hdi/hdbcds: Raise a nice error message for `@sql.append` on managed associations/compositions,
|
|
62
|
+
as we do for structured error messages.
|
|
63
|
+
- to.cdl: Annotations with multiple qualifiers (`#`) are now rendered correctly.
|
|
64
|
+
- to.edm(x): Revert change introduced with [3.9.0](#version-390---2023-04-20)
|
|
65
|
+
"Correct referential constraint calculation for `[0..1]` backlink associations".
|
|
66
|
+
- for.odata: Process shortcut annotations sequence independent.
|
|
67
|
+
- to.sql.migration:
|
|
68
|
+
+ Respect unique and referential constraints for delta calculation.
|
|
69
|
+
+ Added a configurable error for primary key additions, as those will lead to errors if the table
|
|
70
|
+
contains data. This could lead to inconsistent states if
|
|
71
|
+
some deployments succeed and others fail, so by default it is an error.
|
|
72
|
+
|
|
73
|
+
### Removed
|
|
74
|
+
|
|
75
|
+
- Compiler:
|
|
76
|
+
+ forbid wildcards in projection extensions: `extend … with columns { * )`.
|
|
77
|
+
+ forbid column references such as `$user.*`, `$user.{id}` and `$user {id}`.
|
|
10
78
|
|
|
11
79
|
## Version 4.0.2 - 2023-06-22
|
|
12
80
|
|
|
@@ -77,8 +145,6 @@ The compiler behavior concerning `beta` features can change at any time without
|
|
|
77
145
|
+ Table alias and mixin names can no longer start with `$`. Choose a different name. With this change
|
|
78
146
|
we avoid unexpected name resolution effects in combination with built-in `$`-variables.
|
|
79
147
|
+ A semicolon is now required after a type definition like `type T : many {} null`.
|
|
80
|
-
+ It is no longer possible to write `type of $self.‹elem›` to refer to the element `‹Def›.‹elem›`
|
|
81
|
-
where `‹Def›` is the main artifact where the type expression is embedded in. Replace by `type of <Def>:‹elem›`.
|
|
82
148
|
+ Message ID `duplicate-autoexposed` was changed to `def-duplicate-autoexposed`.
|
|
83
149
|
- Update OData vocabularies 'Common', 'UI'.
|
|
84
150
|
- to.sql:
|
|
@@ -96,7 +162,12 @@ The compiler behavior concerning `beta` features can change at any time without
|
|
|
96
162
|
+ `parseCdl` CSN did not include correct `...` entries for annotations containing `... up to`
|
|
97
163
|
+ Type references inside calculated elements were not always correctly resolved.
|
|
98
164
|
+ `USING` empty files were incorrectly marked as "not found".
|
|
165
|
+
+ Correct the handling of `$self` references in nested projections and filters in queries.
|
|
99
166
|
+ If an association was inside `items`, e.g. via type chains, the compiler crashes instead of emitting proper errors.
|
|
167
|
+
+ References in the user-provided `on` conditions of associations with a to be
|
|
168
|
+
auto-redirected model entity as target were not always resolved correctly.
|
|
169
|
+
Complain in error situations.
|
|
170
|
+
+ Make extend code robust against prototype-polluted JS classes.
|
|
100
171
|
- Localized convenience views for projections (not views) did not have references rewritten.
|
|
101
172
|
This only affects CSN, the SQL result was correct.
|
|
102
173
|
- Calculated elements in composition-of-aspect lost their `value` when generating composition targets.
|
|
@@ -116,9 +187,33 @@ The compiler behavior concerning `beta` features can change at any time without
|
|
|
116
187
|
- NodeJs 14 is no longer supported.
|
|
117
188
|
- `CompileMessage` no longer has property `location`, which was deprecated in v2.1.0, but `$location`,
|
|
118
189
|
which is supported since v2.1.0
|
|
119
|
-
-
|
|
120
|
-
|
|
121
|
-
|
|
190
|
+
- compiler:
|
|
191
|
+
+ It is no longer possible to write `type of $self.‹elem›` to refer to the element `‹Def›.‹elem›`
|
|
192
|
+
where `‹Def›` is the main artifact where the type expression is embedded in. Replace by `type of <Def>:‹elem›`.
|
|
193
|
+
+ Element type references can no longer follow associations, i.e. `E:assoc.id` is not allowed
|
|
194
|
+
(v4.0 only, re-introduced with v4.1).
|
|
195
|
+
+ "Smart type references" such as `Entity.myElement` instead of `Entity:myElement`
|
|
196
|
+
are removed, because since - `Entity.myElement` could also be a definition,
|
|
197
|
+
creating ambiguities. This did not work always, anyway.
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
## Version 3.9.6 - 2023-07-27
|
|
201
|
+
|
|
202
|
+
### Fixed
|
|
203
|
+
|
|
204
|
+
- to.edm(x): Revert change introduced with [3.9.0](#version-390---2023-04-20)
|
|
205
|
+
"Correct referential constraint calculation for `[0..1]` backlink associations".
|
|
206
|
+
- for.odata: Process shortcut annotations sequence independent.
|
|
207
|
+
|
|
208
|
+
## Version 3.9.4 - 2023-06-07
|
|
209
|
+
|
|
210
|
+
### Fixed
|
|
211
|
+
|
|
212
|
+
- compiler: `USING` empty files were incorrectly marked as "not found".
|
|
213
|
+
- Localized convenience views for projections (not views) did not have references rewritten.
|
|
214
|
+
This only affects CSN, the SQL result was correct.
|
|
215
|
+
- to.edm(x): Render correct EntitySetPath and annotation target path for actions/functions
|
|
216
|
+
with explicit binding parameter.
|
|
122
217
|
|
|
123
218
|
## Version 3.9.2 - 2023-04-27
|
|
124
219
|
|
package/bin/cdsc.js
CHANGED
|
@@ -499,29 +499,29 @@ function executeCommandLine( command, options, args ) {
|
|
|
499
499
|
|
|
500
500
|
sortMessages(messages);
|
|
501
501
|
|
|
502
|
+
const msgConfig = {
|
|
503
|
+
normalizeFilename,
|
|
504
|
+
noMessageId: !!options.noMessageId,
|
|
505
|
+
hintExplanation: true,
|
|
506
|
+
color: options.color,
|
|
507
|
+
module: options.testMode && 'compile', // TODO: use module name
|
|
508
|
+
sourceMap: fileCache,
|
|
509
|
+
cwd: '',
|
|
510
|
+
};
|
|
511
|
+
|
|
502
512
|
if (options.internalMsg) {
|
|
503
513
|
messages.map(msg => util.inspect( msg, { depth: null, maxArrayLength: null } ) )
|
|
504
514
|
.forEach(msg => log(msg));
|
|
505
515
|
}
|
|
506
516
|
else if (options.noMessageContext) {
|
|
507
517
|
messages.filter(msg => (messageLevels[msg.severity] <= options.warning))
|
|
508
|
-
.forEach(msg => log(main.messageString(msg,
|
|
518
|
+
.forEach(msg => log(main.messageString( msg, msgConfig )));
|
|
509
519
|
}
|
|
510
520
|
else {
|
|
511
521
|
let hasAtLeastOneExplanation = false;
|
|
512
|
-
const config = {
|
|
513
|
-
normalizeFilename,
|
|
514
|
-
noMessageId: !!options.noMessageId,
|
|
515
|
-
hintExplanation: true,
|
|
516
|
-
color: options.color,
|
|
517
|
-
module: options.testMode && 'compile', // TODO: use module name
|
|
518
|
-
sourceMap: fileCache,
|
|
519
|
-
cwd: '',
|
|
520
|
-
};
|
|
521
|
-
|
|
522
522
|
messages.filter(msg => messageLevels[msg.severity] <= options.warning).forEach((msg) => {
|
|
523
523
|
hasAtLeastOneExplanation = hasAtLeastOneExplanation || main.hasMessageExplanation(msg.messageId);
|
|
524
|
-
log(main.messageStringMultiline(msg,
|
|
524
|
+
log(main.messageStringMultiline(msg, msgConfig));
|
|
525
525
|
log(); // newline
|
|
526
526
|
});
|
|
527
527
|
if (!options.noMessageId && hasAtLeastOneExplanation)
|
package/doc/CHANGELOG_BETA.md
CHANGED
|
@@ -8,6 +8,17 @@ Note: `beta` fixes, changes and features are listed in this ChangeLog just for i
|
|
|
8
8
|
The compiler behavior concerning `beta` features can change at any time without notice.
|
|
9
9
|
**Don't use `beta` fixes, changes and features in productive mode.**
|
|
10
10
|
|
|
11
|
+
## Version 4.1.0 - 2023-07-28
|
|
12
|
+
|
|
13
|
+
### Added `associationDefault`
|
|
14
|
+
|
|
15
|
+
With this beta flag enabled, managed associations with exactly one foreign key can now
|
|
16
|
+
have a default value.
|
|
17
|
+
|
|
18
|
+
### Removed `aspectWithoutElements`
|
|
19
|
+
|
|
20
|
+
Aspects without elements can now be defined without beta flag, e.g. `aspect A;`.
|
|
21
|
+
|
|
11
22
|
## Version 4.0.0 - 2023-06-06
|
|
12
23
|
|
|
13
24
|
### Removed `v4preview`
|
package/lib/api/main.js
CHANGED
|
@@ -8,7 +8,7 @@ const location = lazyload('../base/location');
|
|
|
8
8
|
const messages = lazyload('../base/messages');
|
|
9
9
|
const compiler = lazyload('../compiler/index');
|
|
10
10
|
const toCsn = lazyload('../json/to-csn');
|
|
11
|
-
const forOdataNew = lazyload('../transform/
|
|
11
|
+
const forOdataNew = lazyload('../transform/forOdata.js');
|
|
12
12
|
const toSql = lazyload('../render/toSql');
|
|
13
13
|
const toCdl = require('../render/toCdl');
|
|
14
14
|
const modelCompare = lazyload('../modelCompare/compare');
|
|
@@ -95,14 +95,14 @@ function checkPreTransformedCsn( csn, options, relevantOptionNames, warnAboutMis
|
|
|
95
95
|
|
|
96
96
|
for (const name of relevantOptionNames ) {
|
|
97
97
|
if (options[name] !== csn.meta.options?.[name]) {
|
|
98
|
-
error('
|
|
98
|
+
error('api-invalid-option-preprocessed', null, { prop: name, value: options[name], othervalue: csn.meta.options[name] },
|
|
99
99
|
'Expected pre-processed CSN to have option $(PROP) set to $(VALUE). Found: $(OTHERVALUE)');
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
for (const name of warnAboutMismatch ) {
|
|
104
104
|
if (options[name] !== csn.meta.options[name]) {
|
|
105
|
-
warning('
|
|
105
|
+
warning('api-mismatched-option-preprocessed', null, { prop: name, value: options[name], othervalue: csn.meta.options[name] },
|
|
106
106
|
'Expected pre-processed CSN to have option $(PROP) set to $(VALUE). Found: $(OTHERVALUE)');
|
|
107
107
|
}
|
|
108
108
|
}
|
|
@@ -242,8 +242,10 @@ function sql( csn, options = {} ) {
|
|
|
242
242
|
const sqls = toSql.toSqlDdl(transformedCsn, internalOptions);
|
|
243
243
|
|
|
244
244
|
const result = sortViews({ csn: transformedCsn, sql: sqls.sql });
|
|
245
|
-
|
|
246
|
-
|
|
245
|
+
return [
|
|
246
|
+
...result.map(obj => obj.sql).filter(create => create),
|
|
247
|
+
...Object.values(sqls.constraints || {}),
|
|
248
|
+
];
|
|
247
249
|
}
|
|
248
250
|
|
|
249
251
|
/**
|
|
@@ -359,7 +361,9 @@ function remapName( key, csn, filter = () => true ) {
|
|
|
359
361
|
function sqlMigration( csn, options, beforeImage ) {
|
|
360
362
|
traceApi("Options passed into 'to.sql.migration'", options);
|
|
361
363
|
const internalOptions = prepareOptions.to.sql(options);
|
|
362
|
-
const {
|
|
364
|
+
const {
|
|
365
|
+
error, warning, info, throwWithError, message,
|
|
366
|
+
} = messages.makeMessageFunction(csn, internalOptions, 'to.sql.migration');
|
|
363
367
|
|
|
364
368
|
// Prepare after-image.
|
|
365
369
|
const afterImage = internalOptions.filterCsn
|
|
@@ -369,8 +373,12 @@ function sqlMigration( csn, options, beforeImage ) {
|
|
|
369
373
|
const diffFilterObj = diffFilter[internalOptions.sqlDialect];
|
|
370
374
|
|
|
371
375
|
if (diffFilterObj) {
|
|
372
|
-
diff.extensions.
|
|
373
|
-
|
|
376
|
+
diff.extensions = diff.extensions.filter(ex => diffFilterObj.extension(ex, {
|
|
377
|
+
error, warning, info, throwWithError, message,
|
|
378
|
+
}));
|
|
379
|
+
diff.migrations.forEach(migration => diffFilterObj.migration(migration, {
|
|
380
|
+
error, warning, info, throwWithError, message,
|
|
381
|
+
}));
|
|
374
382
|
Object.entries(diff.deletions).forEach(entry => diffFilterObj.deletion(entry, error));
|
|
375
383
|
}
|
|
376
384
|
|
|
@@ -443,8 +451,10 @@ function sqlMigration( csn, options, beforeImage ) {
|
|
|
443
451
|
|
|
444
452
|
internalOptions.beta.sqlExtensions = true;
|
|
445
453
|
|
|
446
|
-
|
|
447
|
-
|
|
454
|
+
const {
|
|
455
|
+
// eslint-disable-next-line no-unused-vars
|
|
456
|
+
deletions, constraintDeletions, migrations, constraints, ...hdbkinds
|
|
457
|
+
} = toSql.toSqlDdl(diff, internalOptions);
|
|
448
458
|
|
|
449
459
|
cleanup.forEach(fn => fn());
|
|
450
460
|
// TODO: Handle `ADD CONSTRAINT` etc!
|
|
@@ -473,6 +483,12 @@ function sqlMigration( csn, options, beforeImage ) {
|
|
|
473
483
|
createAndAlterSqls.push(...migrations[name].map(m => m.sql));
|
|
474
484
|
}
|
|
475
485
|
|
|
486
|
+
if (constraints)
|
|
487
|
+
Object.values(constraints).forEach(constraint => createAndAlterSqls.push(constraint));
|
|
488
|
+
|
|
489
|
+
if (constraintDeletions)
|
|
490
|
+
Object.values(constraintDeletions).forEach(constraint => dropSqls.push(constraint));
|
|
491
|
+
|
|
476
492
|
// We need to drop the things without dependants first - so inversely sorted
|
|
477
493
|
dropSqls.reverse();
|
|
478
494
|
|
|
@@ -510,7 +526,11 @@ function hdiMigration( csn, options, beforeImage ) {
|
|
|
510
526
|
|
|
511
527
|
internalOptions.beta.sqlExtensions = true;
|
|
512
528
|
|
|
513
|
-
|
|
529
|
+
// Ignore constraint drops - that is handled by .hdbconstraint et. al.
|
|
530
|
+
const {
|
|
531
|
+
// eslint-disable-next-line no-unused-vars
|
|
532
|
+
deletions, migrations, constraintDeletions, ...hdbkinds
|
|
533
|
+
} = toSql.toSqlDdl(diff, internalOptions);
|
|
514
534
|
|
|
515
535
|
return {
|
|
516
536
|
afterImage,
|
package/lib/api/validate.js
CHANGED
|
@@ -115,7 +115,7 @@ const validators = {
|
|
|
115
115
|
found: val => `type ${ typeof val }`,
|
|
116
116
|
},
|
|
117
117
|
testMode: {
|
|
118
|
-
validate: val => typeof val === 'boolean' || typeof val === 'number',
|
|
118
|
+
validate: val => typeof val === 'boolean' || typeof val === 'number' || val === '$noAssertConsistency',
|
|
119
119
|
expected: () => 'type boolean|number',
|
|
120
120
|
found: val => `type ${ typeof val }`,
|
|
121
121
|
},
|
package/lib/base/location.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// but not semantic locations (which are message-specific),
|
|
5
5
|
|
|
6
6
|
const { copyPropIfExist } = require('../utils/objectUtils');
|
|
7
|
+
const { CsnLocation } = require('../compiler/classes');
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Create a location with properties `file`, `line` and `col` from argument
|
|
@@ -41,6 +42,7 @@ function combinedLocation( start, end ) {
|
|
|
41
42
|
*/
|
|
42
43
|
function emptyLocation( filename ) {
|
|
43
44
|
return {
|
|
45
|
+
__proto__: CsnLocation.prototype,
|
|
44
46
|
file: filename,
|
|
45
47
|
line: 1,
|
|
46
48
|
col: 1,
|
|
@@ -60,9 +62,12 @@ function emptyLocation( filename ) {
|
|
|
60
62
|
*/
|
|
61
63
|
function emptyWeakLocation( filename ) {
|
|
62
64
|
return {
|
|
65
|
+
__proto__: CsnLocation.prototype,
|
|
63
66
|
file: filename,
|
|
64
67
|
line: 1,
|
|
65
68
|
col: 1,
|
|
69
|
+
endLine: undefined,
|
|
70
|
+
endCol: undefined,
|
|
66
71
|
};
|
|
67
72
|
}
|
|
68
73
|
|
|
@@ -140,13 +145,7 @@ function dictLocation( dict, extraLocation ) {
|
|
|
140
145
|
const lineB = (b.endLine || b.line);
|
|
141
146
|
return (lineA > lineB || (lineA === lineB && (a.endCol || a.col) > (b.endCol || b.col)) ? a : b);
|
|
142
147
|
});
|
|
143
|
-
return
|
|
144
|
-
file: min.file,
|
|
145
|
-
line: min.line,
|
|
146
|
-
col: min.col,
|
|
147
|
-
endLine: max.endLine,
|
|
148
|
-
endCol: max.endCol,
|
|
149
|
-
};
|
|
148
|
+
return new CsnLocation( min.file, min.line, min.col, max.endLine, max.endCol );
|
|
150
149
|
}
|
|
151
150
|
|
|
152
151
|
function _objLocations( obj ) {
|
|
@@ -52,6 +52,7 @@ const centralMessages = {
|
|
|
52
52
|
'anno-unstable-array': { severity: 'Warning' },
|
|
53
53
|
'anno-invalid-sql-element': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
|
|
54
54
|
'anno-invalid-sql-struct': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
|
|
55
|
+
'anno-invalid-sql-assoc': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
|
|
55
56
|
'anno-invalid-sql-calc': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
|
|
56
57
|
'anno-invalid-sql-kind': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
|
|
57
58
|
'anno-invalid-sql-view': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
|
|
@@ -63,46 +64,36 @@ const centralMessages = {
|
|
|
63
64
|
'anno-undefined-param': { severity: 'Warning' },
|
|
64
65
|
'anno-unexpected-ellipsis': { severity: 'Error', configurableFor: 'deprecated' },
|
|
65
66
|
|
|
66
|
-
'args-expecting-named': { severity: 'Error' },
|
|
67
|
-
'args-no-params': { severity: 'Error' },
|
|
68
|
-
'args-undefined-param': { severity: 'Error' },
|
|
69
|
-
|
|
70
67
|
'name-invalid-dollar-alias': { severity: 'Error', configurableFor: true },
|
|
71
68
|
|
|
72
69
|
'type-invalid-items': { severity: 'Error' }, // not supported yet
|
|
73
70
|
'assoc-as-type': { severity: 'Error' }, // TODO: allow more, but not all
|
|
71
|
+
'def-unexpected-nested-proj': { severity: 'Error', configurableFor: 'v4' },
|
|
74
72
|
'def-unexpected-paramview-assoc': { severity: 'Error' },
|
|
75
73
|
'def-unexpected-calcview-assoc': { severity: 'Error' },
|
|
76
74
|
'chained-array-of': { severity: 'Error' },
|
|
77
|
-
'
|
|
75
|
+
'def-missing-type': { severity: 'Error', configurableFor: [ 'compile' ] },
|
|
78
76
|
'check-proper-type-of': { severity: 'Info', errorFor: [ 'for.odata', 'to.edmx', 'to.hdbcds', 'to.sql', 'to.hdi', 'to.rename' ] },
|
|
79
77
|
|
|
80
78
|
'def-duplicate-autoexposed': { severity: 'Error' },
|
|
81
79
|
'def-unexpected-default': { severity: 'Error', configurableFor: 'test' },
|
|
82
80
|
|
|
83
|
-
'expr-
|
|
81
|
+
'expr-unexpected-filter': { severity: 'Error' },
|
|
84
82
|
|
|
85
83
|
'empty-type': { severity: 'Info' }, // only still an error in old transformers
|
|
86
84
|
|
|
87
85
|
'ref-deprecated-orderby': { severity: 'Error', configurableFor: true },
|
|
88
|
-
'ref-
|
|
89
|
-
'ref-sloppy-type': { severity: 'Error' },
|
|
86
|
+
'ref-invalid-type': { severity: 'Error' },
|
|
90
87
|
'ref-unexpected-self': { severity: 'Error' },
|
|
91
|
-
'ref-
|
|
88
|
+
'ref-invalid-include': { severity: 'Error' },
|
|
92
89
|
'type-unexpected-typeof': { severity: 'Error' },
|
|
93
90
|
'type-ignoring-argument': { severity: 'Error', configurableFor: true },
|
|
94
91
|
'type-expected-builtin': { severity: 'Error', configurableFor: true },
|
|
95
92
|
'type-expecting-service-target': { severity: 'Error', configurableFor: true },
|
|
96
|
-
'ref-expecting-action-param-type': { severity: 'Error' },
|
|
97
|
-
'ref-sloppy-actionparam-type': { severity: 'Error' },
|
|
98
|
-
'ref-expecting-event-type': { severity: 'Error' }, // TODO: Test coverage
|
|
99
|
-
'ref-sloppy-event-type': { severity: 'Error' },
|
|
100
|
-
'ref-expecting-struct': { severity: 'Error' },
|
|
101
93
|
'ref-expecting-const': { severity: 'Error' },
|
|
102
|
-
'ref-
|
|
103
|
-
'ref-
|
|
104
|
-
'ref-
|
|
105
|
-
'ref-sloppy-target': { severity: 'Warning' },
|
|
94
|
+
'ref-invalid-source': { severity: 'Error' },
|
|
95
|
+
'ref-invalid-target': { severity: 'Error' },
|
|
96
|
+
'ref-sloppy-target': { severity: 'Error', configurableFor: 'v4' },
|
|
106
97
|
|
|
107
98
|
'extend-repeated-intralayer': { severity: 'Warning' },
|
|
108
99
|
'extend-unrelated-layer': { severity: 'Info' },
|
|
@@ -166,15 +157,13 @@ const centralMessages = {
|
|
|
166
157
|
'syntax-unexpected-sql-clause': { severity: 'Error' }, // TODO: configurableFor:'tests'?
|
|
167
158
|
|
|
168
159
|
'type-managed-composition': { severity: 'Error' },
|
|
169
|
-
'type-unsupported-precision-change': { severity: 'Error'},
|
|
160
|
+
'type-unsupported-precision-change': { severity: 'Error' },
|
|
161
|
+
'type-unsupported-key-change': { severity: 'Error', configurableFor: true },
|
|
170
162
|
|
|
171
163
|
'def-missing-element': { severity: 'Error' },
|
|
172
164
|
|
|
173
165
|
'def-unsupported-calc-elem': { severity: 'Error', configurableFor: true },
|
|
174
166
|
|
|
175
|
-
'unexpected-keys-for-composition': { severity: 'Error' }, // TODO: more than 30 chars
|
|
176
|
-
'unmanaged-as-key': { severity: 'Error' }, // is confusing
|
|
177
|
-
'composition-as-key': { severity: 'Error' }, // is confusing and not supported
|
|
178
167
|
'def-invalid-key-cardinality': { severity: 'Error' },
|
|
179
168
|
// Published! Used in @cap-js-community/odata-v2-adapter; if renamed, add to oldMessageIds
|
|
180
169
|
'odata-spec-violation-array': { severity: 'Warning' }, // more than 30 chars
|
|
@@ -213,6 +202,8 @@ const oldMessageIds = createDict({
|
|
|
213
202
|
'old-anno-duplicate': 'anno-duplicate', // Example
|
|
214
203
|
'assoc-in-array': 'type-invalid-items',
|
|
215
204
|
'duplicate-autoexposed': 'def-duplicate-autoexposed',
|
|
205
|
+
'expr-no-filter': 'expr-unexpected-filter',
|
|
206
|
+
'check-proper-type': 'def-missing-type',
|
|
216
207
|
});
|
|
217
208
|
|
|
218
209
|
// Set up the old-to-new message ID mapping in the message registry.
|
|
@@ -511,7 +502,12 @@ const centralMessageTexts = {
|
|
|
511
502
|
// Messages for erroneous references -----------------------------------------
|
|
512
503
|
// location at erroneous reference (if possible)
|
|
513
504
|
'ref-deprecated-orderby': 'Replace source element reference $(ID) by $(NEWCODE); auto-corrected',
|
|
514
|
-
'ref-unexpected-self':
|
|
505
|
+
'ref-unexpected-self': {
|
|
506
|
+
std: 'Unexpected $(ID) reference; is valid only in ON-conditions of unmanaged associations',
|
|
507
|
+
on: 'Unexpected $(ID) reference; is valid only if compared to be equal to an association of the target side',
|
|
508
|
+
subQuery: 'Unexpected $(ID) reference in a sub query',
|
|
509
|
+
setQuery: 'Unexpected $(ID) reference in a query on the right side of $(OP)',
|
|
510
|
+
},
|
|
515
511
|
'ref-undefined-def': {
|
|
516
512
|
std: 'Artifact $(ART) has not been found',
|
|
517
513
|
// TODO: proposal 'No definition of $(NAME) found',
|
|
@@ -565,7 +561,11 @@ const centralMessageTexts = {
|
|
|
565
561
|
},
|
|
566
562
|
'ref-unexpected-assoc': {
|
|
567
563
|
std: 'Unexpected reference to association $(NAME)', // "std" currently unused
|
|
564
|
+
unmanaged: 'Unexpected reference to an unmanaged association',
|
|
565
|
+
'self-unmanaged': 'Unexpected column reference starting with $(ALIAS) to an unmanaged association',
|
|
566
|
+
self: 'A reference to an unmanaged association is only valid when compared via $(CODE)',
|
|
568
567
|
expr: 'Associations can\'t be used as values in expressions',
|
|
568
|
+
'expr-comp': 'Compositions can\'t be used as values in expressions',
|
|
569
569
|
cast: 'Casting to an association is not supported',
|
|
570
570
|
},
|
|
571
571
|
'ref-unexpected-calculated': {
|
|
@@ -575,7 +575,7 @@ const centralMessageTexts = {
|
|
|
575
575
|
},
|
|
576
576
|
'ref-unexpected-localized': {
|
|
577
577
|
std: 'Unexpected reference to localized element $(NAME)', // "std" currently unused
|
|
578
|
-
calc: 'Calculated elements can\'t refer to localized elements',
|
|
578
|
+
calc: 'Calculated elements "on-write" can\'t refer to localized elements',
|
|
579
579
|
},
|
|
580
580
|
|
|
581
581
|
'ref-unexpected-navigation': {
|
|
@@ -624,6 +624,14 @@ const centralMessageTexts = {
|
|
|
624
624
|
comp: 'Unexpected composition inside $(PROP)',
|
|
625
625
|
},
|
|
626
626
|
|
|
627
|
+
'type-unexpected-default': {
|
|
628
|
+
std: 'Unexpected $(KEYWORD) on an association/composition', // unused
|
|
629
|
+
multi: 'Unexpected $(KEYWORD); expected exactly one foreign key in combination with default value, but found $(COUNT)',
|
|
630
|
+
structured: 'Unexpected $(KEYWORD) in combination with structured foreign key $(NAME); $(KEYWORD) requires a non-structured foreign key',
|
|
631
|
+
'onCond': 'Unexpected $(KEYWORD) on an association/composition with ON-condition; $(KEYWORD) requires exactly one foreign key',
|
|
632
|
+
'targetAspect': 'Unexpected $(KEYWORD) on composition of aspect'
|
|
633
|
+
},
|
|
634
|
+
|
|
627
635
|
'anno-builtin': 'Builtin types should not be annotated. Use custom type instead',
|
|
628
636
|
'anno-undefined-def': 'Artifact $(ART) has not been found', // TODO: ext-
|
|
629
637
|
'anno-undefined-art': 'No artifact has been found with name $(ART)',
|
|
@@ -654,14 +662,25 @@ const centralMessageTexts = {
|
|
|
654
662
|
source: 'Unexpected definition of an association in an entity with parameters',
|
|
655
663
|
target: 'Expected association target to have no parameters',
|
|
656
664
|
},
|
|
665
|
+
'def-unexpected-nested-proj': {
|
|
666
|
+
std: 'Unexpected $(CODE)',
|
|
667
|
+
var: 'Unexpected $(CODE) after reference to CDS variable',
|
|
668
|
+
struct: 'Unexpected $(CODE); can only be used after a reference to a structure or association',
|
|
669
|
+
init: 'Unexpected $(CODE); can only be used after a reference to a structure, association or table alias',
|
|
670
|
+
},
|
|
657
671
|
'def-unexpected-calcview-assoc': {
|
|
658
672
|
std: 'unused',
|
|
659
673
|
'source': 'Unexpected definition of an association in an entity annotated with $(ANNO)',
|
|
660
674
|
'target': 'Expected association target not to be annotated with $(ANNO)',
|
|
661
675
|
},
|
|
676
|
+
'def-invalid-key': {
|
|
677
|
+
std: 'The current element can\'t be defined as primary key', // (unused)
|
|
678
|
+
unmanaged: 'Unmanaged associations/compositions can\'t be defined as primary key',
|
|
679
|
+
composition: 'Managed aspect compositions can\'t be defined as primary key',
|
|
680
|
+
},
|
|
662
681
|
'def-unexpected-key': {
|
|
663
682
|
std: '$(ART) can\'t have additional keys',
|
|
664
|
-
virtual: 'Unexpected $(PROP) for virtual element $(
|
|
683
|
+
virtual: 'Unexpected $(PROP) for virtual element $(ART)',
|
|
665
684
|
// TODO: Better message?
|
|
666
685
|
include: '$(ART) can\'t have additional keys (through include)',
|
|
667
686
|
},
|
|
@@ -725,19 +744,27 @@ const centralMessageTexts = {
|
|
|
725
744
|
missing: 'Expected element $(ID) to have at least all the same sub-elements as included artifacts, but it is missing $(NAME)'
|
|
726
745
|
},
|
|
727
746
|
|
|
728
|
-
'ref-expecting-
|
|
729
|
-
'ref-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
747
|
+
'ref-expecting-const': 'A constant expression or variable is expected here',
|
|
748
|
+
'ref-invalid-target': {
|
|
749
|
+
std: 'An entity, projection or view is expected here', // TODO: change text
|
|
750
|
+
composition: 'Expecting an entity or aspect as composition target',
|
|
751
|
+
bare: 'Expecting the target aspect to have elements',
|
|
752
|
+
aspect: 'Expecting the name of an aspect in property $(PROP)', // only CSN input
|
|
753
|
+
},
|
|
754
|
+
'ref-invalid-include': {
|
|
755
|
+
std: 'A type, entity, aspect or event with direct elements is expected here',
|
|
756
|
+
bare : 'An aspect without elements is expected here',
|
|
757
|
+
},
|
|
758
|
+
'ref-invalid-type': {
|
|
759
|
+
std: 'A type or an element is expected here',
|
|
760
|
+
param: 'A type, an element, or a service entity is expected here',
|
|
761
|
+
event: 'A type, an element, an event, or a service entity is expected here',
|
|
762
|
+
},
|
|
734
763
|
// TODO: text variant if the association does not start an entity
|
|
735
|
-
'ref-
|
|
736
|
-
'ref-expecting-target': 'An entity or an aspect is expected here', // TODO: coverage
|
|
764
|
+
'ref-invalid-source': 'A query source must be an entity or an association',
|
|
737
765
|
'extend-columns': 'Artifact $(ART) can\'t be extended with columns, only projections can',
|
|
738
766
|
'extend-repeated-intralayer': 'Unstable element order due to repeated extensions in same layer',
|
|
739
767
|
'extend-unexpected-include': 'Can\'t extend $(META) with includes',
|
|
740
|
-
'ref-expecting-bare-aspect': 'An aspect without elements is expected here',
|
|
741
768
|
|
|
742
769
|
'ext-duplicate-same-file': 'Duplicate extension with $(PROP) in same file',
|
|
743
770
|
'ext-duplicate-extend-type': 'Duplicate type extension for type $(TYPE)',
|
|
@@ -787,6 +814,8 @@ const centralMessageTexts = {
|
|
|
787
814
|
target: 'Expected target $(TARGET) of specified element $(NAME) to be the same as the inferred element\'s target $(ART)',
|
|
788
815
|
foreignKeys: 'Expected foreign keys of specified element $(NAME) to be the same as the inferred element\'s foreign keys',
|
|
789
816
|
prop: 'Value for $(PROP) of the specified element $(NAME) does not match the inferred element\'s value',
|
|
817
|
+
enumExtra: 'Specified element $(NAME) differs from inferred element: it has an additional enum element $(ID)',
|
|
818
|
+
enumVal: 'Specified element $(NAME) differs from inferred element: it has a different value for enum element $(ID)',
|
|
790
819
|
},
|
|
791
820
|
|
|
792
821
|
'query-unexpected-property': {
|
|
@@ -794,10 +823,7 @@ const centralMessageTexts = {
|
|
|
794
823
|
calculatedElement: 'Unexpected property $(PROP) in the specified element $(NAME); calculated elements are not supported in queries',
|
|
795
824
|
},
|
|
796
825
|
|
|
797
|
-
'ref-sloppy-type': 'A type or an element is expected here',
|
|
798
|
-
'ref-sloppy-actionparam-type': 'A type, an element, or a service entity is expected here',
|
|
799
826
|
'ref-sloppy-target': 'An entity or an aspect (not type) is expected here',
|
|
800
|
-
'ref-sloppy-event-type': 'A type, an element, an event, or a service entity is expected here',
|
|
801
827
|
|
|
802
828
|
'ref-ambiguous': {
|
|
803
829
|
std: 'Replace ambiguous $(ID) by $(NAMES)',
|
|
@@ -812,6 +838,16 @@ const centralMessageTexts = {
|
|
|
812
838
|
entity: 'Entity $(ART) with managed compositions can\'t be used in types', // yet
|
|
813
839
|
},
|
|
814
840
|
|
|
841
|
+
'type-unsupported-key-change': {
|
|
842
|
+
std: 'Added element $(ID) is a primary key change and will not work if the table contains data',
|
|
843
|
+
changed: 'Changed element $(ID) is a primary key change and will not work if the table contains data'
|
|
844
|
+
},
|
|
845
|
+
|
|
846
|
+
'type-unsupported-key-sqlite': {
|
|
847
|
+
std: 'Added element $(ID) is a primary key change and will not work with dialect $(NAME)',
|
|
848
|
+
changed: 'Changed element $(ID) is a primary key change and will not work with dialect $(NAME)'
|
|
849
|
+
},
|
|
850
|
+
|
|
815
851
|
// -----------------------------------------------------------------------------------
|
|
816
852
|
// Expressions
|
|
817
853
|
// -----------------------------------------------------------------------------------
|
|
@@ -820,6 +856,16 @@ const centralMessageTexts = {
|
|
|
820
856
|
std: 'Expected a comparison with $(OP) when using $(ID) in an ON-condition',
|
|
821
857
|
},
|
|
822
858
|
|
|
859
|
+
'type-invalid-cardinality': {
|
|
860
|
+
std: 'Invalid value $(VALUE) for cardinality', // unused variant
|
|
861
|
+
sourceMax: 'Invalid value $(PROP) for maximum source cardinality, expecting a positive number or $(OTHERPROP)',
|
|
862
|
+
targetMax: 'Invalid value $(PROP) for maximum target cardinality, expecting a positive number or $(OTHERPROP)',
|
|
863
|
+
targetMin: 'Invalid value $(PROP) for minimum target cardinality, expecting a non-negative number',
|
|
864
|
+
sourceMin: 'Invalid value $(PROP) for minimum source cardinality, expecting a non-negative number',
|
|
865
|
+
sourceVal: 'Source minimum cardinality must not be greater than source maximum cardinality',
|
|
866
|
+
targetVal: 'Target minimum cardinality must not be greater than target maximum cardinality',
|
|
867
|
+
},
|
|
868
|
+
|
|
823
869
|
'i18n-different-value': 'Different translation for key $(PROP) of language $(OTHERPROP) in unrelated layers',
|
|
824
870
|
|
|
825
871
|
// OData version dependent messages
|
|
@@ -948,7 +994,7 @@ const centralMessageTexts = {
|
|
|
948
994
|
*
|
|
949
995
|
* @typedef {object} MessageConfig
|
|
950
996
|
* @property {MessageSeverity} severity Default severity for the message.
|
|
951
|
-
* @property {string[]|'deprecated'|'v4'|true} [configurableFor]
|
|
997
|
+
* @property {string[]|'deprecated'|'v4'|'test'|true} [configurableFor]
|
|
952
998
|
* Whether the error can be reclassified to a warning or lower.
|
|
953
999
|
* If not `true` then an array is expected with specified modules in which the error is downgradable.
|
|
954
1000
|
* Only has an effect if default severity is 'Error'.
|