@sap/cds-compiler 3.0.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/bin/.eslintrc.json +2 -1
- package/bin/cdsc.js +19 -0
- package/doc/API.md +11 -0
- package/doc/CHANGELOG_ARCHIVE.md +1 -1
- package/doc/CHANGELOG_BETA.md +24 -2
- package/doc/CHANGELOG_DEPRECATED.md +21 -1
- package/lib/api/main.js +7 -7
- package/lib/api/options.js +2 -3
- package/lib/base/message-registry.js +17 -5
- package/lib/base/messages.js +18 -39
- package/lib/base/model.js +2 -0
- package/lib/checks/actionsFunctions.js +8 -7
- package/lib/checks/selectItems.js +96 -14
- package/lib/checks/types.js +5 -8
- package/lib/checks/validator.js +1 -2
- package/lib/compiler/assert-consistency.js +64 -12
- package/lib/compiler/base.js +6 -4
- package/lib/compiler/builtins.js +58 -8
- package/lib/compiler/checks.js +1 -1
- package/lib/compiler/define.js +25 -22
- package/lib/compiler/extend.js +16 -10
- package/lib/compiler/finalize-parse-cdl.js +5 -9
- package/lib/compiler/index.js +2 -0
- package/lib/compiler/populate.js +34 -31
- package/lib/compiler/propagator.js +11 -6
- package/lib/compiler/resolve.js +14 -15
- package/lib/compiler/shared.js +53 -26
- package/lib/compiler/tweak-assocs.js +5 -11
- package/lib/compiler/utils.js +13 -4
- package/lib/edm/annotations/preprocessAnnotations.js +8 -4
- package/lib/edm/csn2edm.js +3 -3
- package/lib/edm/edm.js +9 -1
- package/lib/edm/edmAnnoPreprocessor.js +349 -0
- package/lib/edm/edmInboundChecks.js +85 -0
- package/lib/edm/edmPreprocessor.js +295 -638
- package/lib/edm/edmUtils.js +85 -5
- package/lib/gen/Dictionary.json +29 -9
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -2
- package/lib/gen/languageLexer.js +3 -0
- package/lib/gen/languageParser.js +4344 -4530
- package/lib/inspect/.eslintrc.json +4 -0
- package/lib/inspect/index.js +14 -0
- package/lib/inspect/inspectModelStatistics.js +81 -0
- package/lib/inspect/inspectPropagation.js +189 -0
- package/lib/inspect/inspectUtils.js +44 -0
- package/lib/json/from-csn.js +3 -2
- package/lib/json/to-csn.js +8 -6
- package/lib/language/genericAntlrParser.js +121 -63
- package/lib/language/language.g4 +19 -57
- package/lib/main.d.ts +1 -0
- package/lib/model/api.js +1 -1
- package/lib/model/csnRefs.js +55 -29
- package/lib/model/csnUtils.js +11 -7
- package/lib/model/revealInternalProperties.js +2 -3
- package/lib/modelCompare/compare.js +3 -0
- package/lib/optionProcessor.js +27 -0
- package/lib/render/toCdl.js +57 -32
- package/lib/render/toSql.js +24 -8
- package/lib/render/utils/common.js +3 -4
- package/lib/transform/db/associations.js +43 -35
- package/lib/transform/db/cdsPersistence.js +0 -1
- package/lib/transform/db/flattening.js +3 -4
- package/lib/transform/db/transformExists.js +7 -5
- package/lib/transform/draft/db.js +1 -1
- package/lib/transform/forHanaNew.js +11 -2
- package/lib/transform/forOdataNew.js +1 -1
- package/lib/transform/odata/typesExposure.js +14 -5
- package/lib/utils/moduleResolve.js +0 -1
- package/package.json +2 -2
- package/lib/checks/unknownMagic.js +0 -41
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,55 @@
|
|
|
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.1.0 - 2022-08-04
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Extending an artifact with multiple includes in one extend statement is now possible:
|
|
15
|
+
`extend SomeEntity with FirstInclude, SecondInclude;`
|
|
16
|
+
- Aspects can now have actions and functions, similar to entities. Aspects can be extended by actions as well.
|
|
17
|
+
- `cdsc`:
|
|
18
|
+
- `toCsn` now supports `--with-locations` which adds a `$location` property to artifacts
|
|
19
|
+
- `toHana`/`toSql` now supports `--disable-hana-comments`, which disables rendering of doc-comments for HANA.
|
|
20
|
+
- to.hdi/sql/hdbcds: Support FK-access in `ORDER BY` and `GROUP BY`
|
|
21
|
+
- to.hdi.migration: Detect an implicit change from `not null` to `null` and render corresponding `ALTER`
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- compiler: If an unknown file extension is used but the file starts with
|
|
26
|
+
an opening curly brace (`{`), it will be parsed as CSN.
|
|
27
|
+
- to.edm(x): In V4 containment mode, pull up `@Capabilities` annotations from the containees to the root container (set)
|
|
28
|
+
and translate them into corresponding `@Capabilities.NavigationRestrictions`. If a `NavigationRestriction` is already available
|
|
29
|
+
for that containment path, capabilities are merged into this path. Capability annotation value paths are prefixed with
|
|
30
|
+
the navigation restriction path.
|
|
31
|
+
The capability 'pull up' has an effect on entity annotations only. `@Capabilities` assignments on compositions are not pulled
|
|
32
|
+
up but rendered to the association type which is important to enable dynamic capabilities on 'to-many' relations and to avoid
|
|
33
|
+
ambiguities in entity set capabilities.
|
|
34
|
+
- Update OData vocabularies 'Analytics', 'Capabilities', 'Common', 'Core', 'DataIntegration', 'Graph', 'PersonalData', 'UI', 'Validation'.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- Syntax of date/time literals are now checked against ISO 8601. If the format is invalid, a warning is emitted.
|
|
39
|
+
- The code completion directly after the `(` for functions with special syntax
|
|
40
|
+
now suggests all valid keywords, like for `extract` or `locate_regexpr`.
|
|
41
|
+
- compiler:
|
|
42
|
+
+ `cast(elem as EnumType)` crashed the compiler.
|
|
43
|
+
+ Annotations on sub-elements in query entities were lost during re-compilation.
|
|
44
|
+
+ An association's cardinality was lost for associations published in projections.
|
|
45
|
+
+ Annotations on indirect action parameters were lost in CSN flavor `gensrc`.
|
|
46
|
+
+ If a file's content starts with `{` and if neither file extension is known nor
|
|
47
|
+
`fallbackParser` is set, assume the source is CSN.
|
|
48
|
+
- all backends: references in `order by` _expressions_ are correctly resolved.
|
|
49
|
+
- to.edm(x):
|
|
50
|
+
+ Allow cross service references for unmanaged associations and improve warning message for muted associations.
|
|
51
|
+
+ Nested `@UI.TextArrangement` has precedence over `@TextArrangement` shortcut annotation for `@Common.Text`.
|
|
52
|
+
- to.hdi.migration:
|
|
53
|
+
+ Doc comments rendered the _full doc comment_ instead of only the first paragraph, as `to.hdi` does.
|
|
54
|
+
+ Respect option `disableHanaComments` when rendering the `ALTER` statements
|
|
55
|
+
- to.hdi/sql/hdbcds:
|
|
56
|
+
+ Check for invalid usages of `$self` and give helpful errors
|
|
57
|
+
+ Correctly resolve association-steps in the from-clause in conjunction with `exists`
|
|
58
|
+
|
|
10
59
|
## Version 3.0.2 - 2022-07-05
|
|
11
60
|
|
|
12
61
|
### Fixed
|
|
@@ -59,6 +108,22 @@ The compiler behavior concerning `beta` features can change at any time without
|
|
|
59
108
|
it is now only allowed for `count`, `min`, `max`, `sum`, `avg`, `stddev`, `var`.
|
|
60
109
|
- All non-SNAPI options.
|
|
61
110
|
|
|
111
|
+
## Version 2.15.8 - 2022-08-02
|
|
112
|
+
|
|
113
|
+
### Fixed
|
|
114
|
+
|
|
115
|
+
- to.edm(x): Nested `@UI.TextArrangement` has precedence over `@TextArrangement` shortcut annotation for `@Common.Text`.
|
|
116
|
+
- to.hdi.migration:
|
|
117
|
+
+ Respect option `disableHanaComments` when rendering the `ALTER` statements
|
|
118
|
+
+ Doc comments rendered the _full doc comment_ instead of only the first paragraph, as `to.hdi` does.
|
|
119
|
+
- compiler: An association's cardinality was lost for associations published in projections.
|
|
120
|
+
|
|
121
|
+
## Version 2.15.6 - 2022-07-26
|
|
122
|
+
|
|
123
|
+
### Fixed
|
|
124
|
+
|
|
125
|
+
- Annotations on sub-elements were lost during re-compilation.
|
|
126
|
+
|
|
62
127
|
## Version 2.15.4 - 2022-06-09
|
|
63
128
|
|
|
64
129
|
### Fixed
|
package/bin/.eslintrc.json
CHANGED
package/bin/cdsc.js
CHANGED
|
@@ -262,6 +262,7 @@ function executeCommandLine(command, options, args) {
|
|
|
262
262
|
toRename,
|
|
263
263
|
manageConstraints,
|
|
264
264
|
toSql,
|
|
265
|
+
inspect,
|
|
265
266
|
};
|
|
266
267
|
const commandsWithoutCompilation = {
|
|
267
268
|
explain,
|
|
@@ -425,6 +426,24 @@ function executeCommandLine(command, options, args) {
|
|
|
425
426
|
console.log(explainMessage(args.messageId));
|
|
426
427
|
}
|
|
427
428
|
|
|
429
|
+
function inspect(model) {
|
|
430
|
+
const inspectModel = require('../lib/inspect');
|
|
431
|
+
|
|
432
|
+
if (options.statistics) {
|
|
433
|
+
const result = inspectModel.inspectModelStatistics(model, options);
|
|
434
|
+
if (result)
|
|
435
|
+
console.log(result);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if (options.propagation) {
|
|
439
|
+
const result = inspectModel.inspectPropagation(model, options, options.propagation);
|
|
440
|
+
if (result)
|
|
441
|
+
console.log(result);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return model;
|
|
445
|
+
}
|
|
446
|
+
|
|
428
447
|
// Display error messages in `err` resulting from a compilation. Also set
|
|
429
448
|
// process.exitCode - process.exit() will force the process to exit as quickly
|
|
430
449
|
// as possible = is problematic, since console.error() might be asynchronous
|
package/doc/API.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# CDS Compiler API Documentation
|
|
2
|
+
|
|
3
|
+
The API of `@sap/cds-compiler` is described in a TypeScript declaration file
|
|
4
|
+
[`main.d.ts`](../lib/main.d.ts).
|
|
5
|
+
|
|
6
|
+
Refer to that file for documentation on option names, API calls, and more.
|
|
7
|
+
|
|
8
|
+
You can use [TypeDoc] to render an HTML documentation from it.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
[TypeDoc]: https://typedoc.org/
|
package/doc/CHANGELOG_ARCHIVE.md
CHANGED
|
@@ -270,7 +270,7 @@ The compiler behaviour concerning `beta` features can change at any time without
|
|
|
270
270
|
- to.sql/hdi/hdbcds:
|
|
271
271
|
+ Doc comments are translated into HANA comments (or into `@Comment` annotation for `to.hdbcds`).
|
|
272
272
|
Such comments are possible on entities, views, elements of entities and `to.hdbcds` also supports comments on view columns.
|
|
273
|
-
Generation can be disabled via option `disableHanaComments`.
|
|
273
|
+
Generation can be disabled via option `disableHanaComments`. Entities/views (and their elements/columns)
|
|
274
274
|
annotated with `@cds.persistence.journal` for `to.hdi`/`to.sql` will not have comments rendered.
|
|
275
275
|
+ Generation of temporal `WHERE` clause can be suppressed by annotating the `validFrom`/`validTo` elements of the projection with `false` or `null`.
|
|
276
276
|
- to.sql/hdi/hdbcds/edm(x)/for.odata: Structure/managed association comparisons (tuple comparisons) are now
|
package/doc/CHANGELOG_BETA.md
CHANGED
|
@@ -8,7 +8,29 @@ 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 3.
|
|
11
|
+
## Version 3.1.0 - 2022-08-04
|
|
12
|
+
|
|
13
|
+
### Added `optionalActionFunctionParameters`
|
|
14
|
+
|
|
15
|
+
- to.edm(x): Annotate optional function/action parameters with `@Core.OptionalParameter` for OData V4.
|
|
16
|
+
An action/function parameter is optional if
|
|
17
|
+
1) it is already annotated with `@Core.OptionalParameter` regardless of its definition.
|
|
18
|
+
2) it has a default value (including null), regardless of it's nullability
|
|
19
|
+
3) it has NO default value but is nullable (the implicit default value is null)
|
|
20
|
+
|
|
21
|
+
If a mandatory parameter (not null and no default value) appears after an optional
|
|
22
|
+
parameter, a warning is raised, Core.OptionalParameter requires that all optional
|
|
23
|
+
parameters appear rightmost.
|
|
24
|
+
|
|
25
|
+
### Added `odataOpenType`
|
|
26
|
+
|
|
27
|
+
- to.edm(x): Support annotation `@open` on entity and structured type level to declare the corresponding entity/complex type to
|
|
28
|
+
be `OpenType=true`. If an open structured type is declared closed (with a falsy annotation value), the corresponding EDM type
|
|
29
|
+
is closed as well and suffixed with `_closed` (or `_open` vice versa).
|
|
30
|
+
No further checks are performed on possibly open foreign or primary key types nor on eventually bucket elements to store the
|
|
31
|
+
additional data.
|
|
32
|
+
|
|
33
|
+
## Version 3.0.0 - 2022-06-23
|
|
12
34
|
|
|
13
35
|
### Removed `addTextsLanguageAssoc`
|
|
14
36
|
|
|
@@ -134,7 +156,7 @@ When the beta option `subElemRedirections` is set to true,
|
|
|
134
156
|
_all_ array (new!) and structure types are expanded when referenced:
|
|
135
157
|
managed associations (and compositions to entities) in that array are
|
|
136
158
|
implicitly redirected when necessary.
|
|
137
|
-
See [below for details](#version-1300---
|
|
159
|
+
See [below for details](#version-1300---2020-06-12).
|
|
138
160
|
|
|
139
161
|
Nested array types (without intermediate structure types) are not supported.
|
|
140
162
|
|
|
@@ -11,10 +11,28 @@ Note: `deprecated` features are listed in this ChangeLog just for information.
|
|
|
11
11
|
**When the `deprecated` option is set, the `beta` option is ignored,
|
|
12
12
|
and several new features are not available.**
|
|
13
13
|
|
|
14
|
-
## Version 3.
|
|
14
|
+
## Version 3.1.0 - 2022-08-04
|
|
15
|
+
|
|
16
|
+
### Added `autoCorrectOrderBySourceRefs`
|
|
17
|
+
|
|
18
|
+
When this option is set, calling `compile` auto-corrects direct `order by`
|
|
19
|
+
source element references without table alias for SELECT queries by adding the
|
|
20
|
+
table alias to the `ref`.
|
|
21
|
+
|
|
22
|
+
Using this option might lead to surprising results when elements are added to
|
|
23
|
+
existing models: `order by` specifications might change their semantics without
|
|
24
|
+
any extra messages.
|
|
25
|
+
|
|
26
|
+
## Version 3.0.0 - 2022-06-23
|
|
15
27
|
|
|
16
28
|
Version 3 of the cds-compiler removes all v2 deprecated flags.
|
|
17
29
|
|
|
30
|
+
### Add `eagerPersistenceForGeneratedEntities`
|
|
31
|
+
|
|
32
|
+
If enabled, the old behavior regarding `@cds.persistence.skip` and `@cds.persistence.exists`
|
|
33
|
+
is restored, i.e. these annotations are not copied from parent to generated child entities, nor
|
|
34
|
+
is `@cds.persistence.exists` copied to localized convenience views.
|
|
35
|
+
|
|
18
36
|
### Removed `createLocalizedViews`
|
|
19
37
|
|
|
20
38
|
### Removed `downgradableErrors`
|
|
@@ -25,6 +43,8 @@ Version 3 of the cds-compiler removes all v2 deprecated flags.
|
|
|
25
43
|
|
|
26
44
|
### Removed `noElementsExpansion`
|
|
27
45
|
|
|
46
|
+
<!-- fully removed with 3.1.0 -->
|
|
47
|
+
|
|
28
48
|
### Removed `noInheritedAutoexposeViaComposition`
|
|
29
49
|
|
|
30
50
|
### Removed `noScopedRedirections`
|
package/lib/api/main.js
CHANGED
|
@@ -408,10 +408,10 @@ function hdiMigration(csn, options, beforeImage) {
|
|
|
408
408
|
}
|
|
409
409
|
|
|
410
410
|
/**
|
|
411
|
-
* From the given SQLs, create the
|
|
411
|
+
* From the given SQLs, create the correct result structure.
|
|
412
412
|
*
|
|
413
|
-
* @param {object} hdbkinds
|
|
414
|
-
* @param {CSN.Model} afterImage
|
|
413
|
+
* @param {object} hdbkinds Object of hdbkinds (such as `hdbindex`) mapped to dictionary of artifacts.
|
|
414
|
+
* @param {CSN.Model} afterImage CSN, used to create correct file names in result structure.
|
|
415
415
|
* @returns {object[]} Array of objects, each having: name, suffix and sql
|
|
416
416
|
*/
|
|
417
417
|
function createSqlDefinitions(hdbkinds, afterImage) {
|
|
@@ -430,8 +430,8 @@ function createSqlDefinitions(hdbkinds, afterImage) {
|
|
|
430
430
|
/**
|
|
431
431
|
* From the given deletions, create the correct result structure.
|
|
432
432
|
*
|
|
433
|
-
* @param {object} deletions
|
|
434
|
-
* @param {CSN.Model} beforeImage
|
|
433
|
+
* @param {object} deletions Dictionary of deletions, only keys are used.
|
|
434
|
+
* @param {CSN.Model} beforeImage CSN used to create correct file names in result structure.
|
|
435
435
|
* @returns {object[]} Array of objects, each having: name and suffix - only .hdbtable as suffix for now
|
|
436
436
|
*/
|
|
437
437
|
function createSqlDeletions(deletions, beforeImage) {
|
|
@@ -442,8 +442,8 @@ function createSqlDeletions(deletions, beforeImage) {
|
|
|
442
442
|
/**
|
|
443
443
|
* From the given migrations, create the correct result structure.
|
|
444
444
|
*
|
|
445
|
-
* @param {object} migrations
|
|
446
|
-
* @param {CSN.Model} afterImage
|
|
445
|
+
* @param {object} migrations Dictionary of changesets (migrations).
|
|
446
|
+
* @param {CSN.Model} afterImage CSN used to create correct file names in result structure.
|
|
447
447
|
* @returns {object[]} Array of objects, each having: name, suffix and changeset.
|
|
448
448
|
*/
|
|
449
449
|
function createSqlMigrations(migrations, afterImage) {
|
package/lib/api/options.js
CHANGED
|
@@ -57,9 +57,7 @@ const privateOptions = [
|
|
|
57
57
|
'noRecompile',
|
|
58
58
|
'internalMsg',
|
|
59
59
|
'disableHanaComments', // in case of issues with hana comment rendering
|
|
60
|
-
'
|
|
61
|
-
'longAutoexposed', // deprecated, no effect - TODO: safe to remove?
|
|
62
|
-
'localizedWithoutCoalesce', // deprecated version of 'localizedLanguageFallback',
|
|
60
|
+
'localizedWithoutCoalesce', // deprecated version of 'localizedLanguageFallback', TODO(v4): Remove option
|
|
63
61
|
];
|
|
64
62
|
|
|
65
63
|
const overallOptions = publicOptionsNewAPI.concat(privateOptions);
|
|
@@ -159,6 +157,7 @@ module.exports = {
|
|
|
159
157
|
return translateOptions(options, defaultOptions, hardOptions, undefined, undefined, 'for.hana');
|
|
160
158
|
},
|
|
161
159
|
},
|
|
160
|
+
overallOptions, // exported for testing
|
|
162
161
|
};
|
|
163
162
|
|
|
164
163
|
|
|
@@ -114,7 +114,7 @@ const centralMessages = {
|
|
|
114
114
|
'ref-undefined-def': { severity: 'Error' },
|
|
115
115
|
'ref-undefined-var': { severity: 'Error' },
|
|
116
116
|
'ref-undefined-element': { severity: 'Error' },
|
|
117
|
-
'ref-unknown-var': { severity: 'Info' },
|
|
117
|
+
'ref-unknown-var': { severity: 'Info', errorFor: [ 'to.hdbcds', 'to.sql', 'to.hdi', 'to.rename' ] },
|
|
118
118
|
'ref-obsolete-parameters': { severity: 'Error', configurableFor: true }, // does not hurt us
|
|
119
119
|
'ref-undefined-param': { severity: 'Error' },
|
|
120
120
|
'ref-rejected-on': { severity: 'Error' },
|
|
@@ -131,6 +131,10 @@ const centralMessages = {
|
|
|
131
131
|
'service-nested-context': { severity: 'Error', configurableFor: true }, // does not hurt compile, TODO
|
|
132
132
|
'service-nested-service': { severity: 'Error', configurableFor: 'deprecated' }, // not supported yet
|
|
133
133
|
|
|
134
|
+
// 'syntax-duplicate-annotate' came late with v3 - make it configurable as
|
|
135
|
+
// fallback, but then parse.cdl is not supposed to work correctly (it can
|
|
136
|
+
// then either issue an error or produce a CSN missing some annotations):
|
|
137
|
+
'syntax-duplicate-annotate': { severity: 'Error', configurableFor: true },
|
|
134
138
|
'syntax-expected-cardinality': { severity: 'Error' },
|
|
135
139
|
'syntax-expected-length': { severity: 'Error' },
|
|
136
140
|
'syntax-expected-translation': { severity: 'Error' },
|
|
@@ -205,7 +209,7 @@ for (const oldName in oldMessageIds) {
|
|
|
205
209
|
// For messageIds, where no text has been provided via code (central def)
|
|
206
210
|
const centralMessageTexts = {
|
|
207
211
|
'api-invalid-option': {
|
|
208
|
-
std: 'Option $(NAME) is
|
|
212
|
+
std: 'Option $(NAME) is no longer supported! Use SNAPI options instead',
|
|
209
213
|
magicVars: 'Option “magicVars” is no longer supported! Use “variableReplacements” instead. See <https://cap.cloud.sap/docs/guides/databases#configuring-variables> for details',
|
|
210
214
|
user: 'Option “variableReplacements” expects “$user” instead of “user”. See <https://cap.cloud.sap/docs/guides/databases#configuring-variables> for details',
|
|
211
215
|
locale: 'Option “variableReplacements” expects “$user.locale” instead of “locale”. See <https://cap.cloud.sap/docs/guides/databases#configuring-variables> for details',
|
|
@@ -228,6 +232,10 @@ const centralMessageTexts = {
|
|
|
228
232
|
'flatten-fkey-exists': 'Generated foreign key element $(NAME) for association $(ART) conflicts with existing element',
|
|
229
233
|
},
|
|
230
234
|
|
|
235
|
+
'syntax-anno-ignored': {
|
|
236
|
+
std: 'Annotations can\'t be used at prefix references',
|
|
237
|
+
doc: 'Doc comments can\'t be used at prefix references',
|
|
238
|
+
},
|
|
231
239
|
'syntax-unexpected-ellipsis': {
|
|
232
240
|
std: 'Expected no more than one $(CODE)',
|
|
233
241
|
'nested-array': 'Unexpected $(CODE) in nested array'
|
|
@@ -276,7 +284,7 @@ const centralMessageTexts = {
|
|
|
276
284
|
unknown: 'Unknown argument $(CODE)',
|
|
277
285
|
duplicate: 'Duplicate argument $(CODE)',
|
|
278
286
|
},
|
|
279
|
-
'syntax-duplicate-annotate': 'You
|
|
287
|
+
'syntax-duplicate-annotate': 'You can\'t refer to $(NAME) repeatedly with property $(PROP) in the same annotate statement',
|
|
280
288
|
'syntax-duplicate-extend': {
|
|
281
289
|
std: 'You can\'t define and refer to $(NAME) repeatedly in the same extend statement',
|
|
282
290
|
define: 'You can\'t refer to $(NAME) in the same extend statement where it was defined',
|
|
@@ -309,7 +317,7 @@ const centralMessageTexts = {
|
|
|
309
317
|
aspect: 'Element $(ID) has not been found in the anonymous target aspect'
|
|
310
318
|
},
|
|
311
319
|
'ref-unknown-var': {
|
|
312
|
-
std: '
|
|
320
|
+
std: 'No replacement found for special variable $(ID)'
|
|
313
321
|
},
|
|
314
322
|
'ref-unexpected-draft-enabled': 'Composition in draft-enabled entity can\'t lead to another entity with $(ANNO)',
|
|
315
323
|
'ref-rejected-on': {
|
|
@@ -467,7 +475,11 @@ const centralMessageTexts = {
|
|
|
467
475
|
std: 'Entity can\'t be created due to name collision with existing definition $(NAME)',
|
|
468
476
|
proxy: 'No proxy entity created due to name collision with existing definition $(NAME) of kind $(KIND)'
|
|
469
477
|
},
|
|
470
|
-
'odata-navigation':
|
|
478
|
+
'odata-navigation': {
|
|
479
|
+
std: 'No OData navigation property generated, target $(TARGET) is outside of service $(SERVICE)',
|
|
480
|
+
oncond: 'No OData navigation property generated for association with arbitrary ON condition and target $(TARGET) outside of service $(SERVICE)'
|
|
481
|
+
},
|
|
482
|
+
'odata-parameter-order': 'Unexpected mandatory after optional parameter',
|
|
471
483
|
}
|
|
472
484
|
|
|
473
485
|
/**
|
package/lib/base/messages.js
CHANGED
|
@@ -8,7 +8,6 @@ const { term } = require('../utils/term');
|
|
|
8
8
|
const { locationString } = require('./location');
|
|
9
9
|
const { isDeprecatedEnabled } = require('./model');
|
|
10
10
|
const { centralMessages, centralMessageTexts, oldMessageIds } = require('./message-registry');
|
|
11
|
-
const { copyPropIfExist } = require('../utils/objectUtils');
|
|
12
11
|
const _messageIdsWithExplanation = require('../../share/messages/message-explanations.json').messages;
|
|
13
12
|
const { analyseCsnPath, traverseQuery } = require('../model/csnRefs');
|
|
14
13
|
const { CompilerAssertion } = require("./error");
|
|
@@ -135,7 +134,7 @@ class CompileMessage {
|
|
|
135
134
|
constructor(location, msg, severity = 'Error', id = null, home = null, moduleName = null) {
|
|
136
135
|
this.message = msg;
|
|
137
136
|
this.location = location;
|
|
138
|
-
this.$location =
|
|
137
|
+
this.$location = { ...this.location, address: undefined };
|
|
139
138
|
this.validNames = null;
|
|
140
139
|
if (home) // semantic location, e.g. 'entity:"E"/element:"x"'
|
|
141
140
|
this.home = home;
|
|
@@ -152,33 +151,6 @@ class CompileMessage {
|
|
|
152
151
|
}
|
|
153
152
|
}
|
|
154
153
|
|
|
155
|
-
/**
|
|
156
|
-
* Temporary v1 function to convert an "old-style" location to "new-style".
|
|
157
|
-
*
|
|
158
|
-
* @param {CSN.Location} location
|
|
159
|
-
* @return {CSN.Location}
|
|
160
|
-
* @todo Remove
|
|
161
|
-
*/
|
|
162
|
-
function dollarLocation( location ) {
|
|
163
|
-
const file = location && location.file || undefined;
|
|
164
|
-
if (!file)
|
|
165
|
-
return {};
|
|
166
|
-
const loc = {
|
|
167
|
-
file,
|
|
168
|
-
line: location.line,
|
|
169
|
-
col: location.col,
|
|
170
|
-
address: undefined,
|
|
171
|
-
};
|
|
172
|
-
copyPropIfExist(location, 'endLine', loc);
|
|
173
|
-
copyPropIfExist(location, 'endCol', loc);
|
|
174
|
-
// TODO:
|
|
175
|
-
// return {
|
|
176
|
-
// ...location,
|
|
177
|
-
// address: undefined,
|
|
178
|
-
// };
|
|
179
|
-
return loc;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
154
|
const severitySpecs = {
|
|
183
155
|
error: { name: 'Error', level: 0 },
|
|
184
156
|
warning: { name: 'Warning', level: 1 },
|
|
@@ -257,14 +229,16 @@ function compareSeverities( a, b ) {
|
|
|
257
229
|
}
|
|
258
230
|
|
|
259
231
|
/**
|
|
260
|
-
*
|
|
232
|
+
* Find the nearest $location for the given CSN path in the model.
|
|
233
|
+
* If the path does not exist, the parent is used, and so on.
|
|
234
|
+
*
|
|
261
235
|
* @param {CSN.Model} model
|
|
262
236
|
* @param {CSN.Path} csnPath
|
|
237
|
+
* @returns {CSN.Location | null}
|
|
263
238
|
*/
|
|
264
|
-
function
|
|
239
|
+
function findNearestLocationForPath( model, csnPath ) {
|
|
265
240
|
if (!model)
|
|
266
241
|
return null;
|
|
267
|
-
// Don't display a location if we cannot find one!
|
|
268
242
|
let lastLocation = null;
|
|
269
243
|
/** @type {object} */
|
|
270
244
|
let currentStep = model;
|
|
@@ -438,7 +412,7 @@ function makeMessageFunction( model, options, moduleName = null ) {
|
|
|
438
412
|
const isCsnPath = (typeof location[0] === 'string'); // could be `definitions`, `extensions`, ....
|
|
439
413
|
if (isCsnPath) {
|
|
440
414
|
return [
|
|
441
|
-
|
|
415
|
+
findNearestLocationForPath( model, location ),
|
|
442
416
|
constructSemanticLocationFromCsnPath( location, model ),
|
|
443
417
|
location[1] // location[0] is 'definitions'
|
|
444
418
|
];
|
|
@@ -1086,9 +1060,10 @@ function compareMessageSeverityAware( a, b ) {
|
|
|
1086
1060
|
* @param {CompileMessage} msg
|
|
1087
1061
|
*/
|
|
1088
1062
|
function homeSortName( { home, messageId } ) {
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1063
|
+
if (!home)
|
|
1064
|
+
return (messageId && /^(syntax|api)-/.test( messageId ) ? ' ' + messageId : '~')
|
|
1065
|
+
else
|
|
1066
|
+
return home.substring( home.indexOf(':') ); // i.e. starting with the ':', is always there
|
|
1092
1067
|
}
|
|
1093
1068
|
|
|
1094
1069
|
/**
|
|
@@ -1192,8 +1167,8 @@ function homeNameForExtend( art ) {
|
|
|
1192
1167
|
const kind = art.kind || 'extend';
|
|
1193
1168
|
// TODO: fix the following - do like in collectArtifactExtensions() or
|
|
1194
1169
|
// basically resolveUncheckedPath()
|
|
1195
|
-
const absoluteName = art.name.id ? art.name.id :
|
|
1196
|
-
(!art.name.element && art.name.absolute ||
|
|
1170
|
+
const absoluteName = art.name.id != null ? art.name.id :
|
|
1171
|
+
(!art.name.element && art.name.absolute || art.name.path && art.name.path.map(s => s && s.id).join('.'));
|
|
1197
1172
|
|
|
1198
1173
|
// Surrounding parent may be another extension.
|
|
1199
1174
|
const parent = art._parent;
|
|
@@ -1383,8 +1358,12 @@ function constructSemanticLocationFromCsnPath(csnPath, model) {
|
|
|
1383
1358
|
if (typeof step === 'number') {
|
|
1384
1359
|
if (currentThing.as)
|
|
1385
1360
|
result += `:${ _quoted(currentThing.as) }`;
|
|
1361
|
+
else if (inRef)
|
|
1362
|
+
result += `:${ _quoted(currentThing) }`;
|
|
1363
|
+
else if (currentThing.ref)
|
|
1364
|
+
result += `:${ _quoted(currentThing.ref.map(r => r.id ? r.id : r).join('.')) }`;
|
|
1386
1365
|
else
|
|
1387
|
-
|
|
1366
|
+
return'';
|
|
1388
1367
|
|
|
1389
1368
|
break;
|
|
1390
1369
|
}
|
package/lib/base/model.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { isBuiltinType } = require('../model/csnUtils');
|
|
4
|
+
const { isBetaEnabled } = require('../base/model');
|
|
4
5
|
|
|
5
6
|
// Only to be used with validator.js - a correct this value needs to be provided!
|
|
6
7
|
|
|
@@ -52,13 +53,13 @@ function checkActionOrFunction(art, artName, prop, path) {
|
|
|
52
53
|
function checkActionOrFunctionParameter(param, currPath, actKind) {
|
|
53
54
|
const paramType = param.type ? this.csnUtils.getFinalTypeDef(param.type) : param;
|
|
54
55
|
|
|
55
|
-
if (param.default || paramType.default) {
|
|
56
|
-
this.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
if (!isBetaEnabled(this.options, 'optionalActionFunctionParameters') && (param.default || paramType.default)) {
|
|
57
|
+
this.message('param-default', currPath, { '#': actKind },
|
|
58
|
+
{
|
|
59
|
+
std: 'Artifact parameters can\'t have a default value', // Not used
|
|
60
|
+
action: 'Action parameters can\'t have a default value',
|
|
61
|
+
function: 'Function parameters can\'t have a default value',
|
|
62
|
+
});
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
if (paramType.type && this.csnUtils.isAssocOrComposition(param.type)) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { forEachGeneric } = require('../model/csnUtils');
|
|
3
|
+
const { forEachGeneric, applyTransformationsOnNonDictionary } = require('../model/csnUtils');
|
|
4
4
|
|
|
5
5
|
// Only to be used with validator.js - a correct this value needs to be provided!
|
|
6
6
|
|
|
@@ -17,21 +17,103 @@ function validateSelectItems(query) {
|
|
|
17
17
|
const { SELECT } = query;
|
|
18
18
|
if (!SELECT)
|
|
19
19
|
return;
|
|
20
|
+
/**
|
|
21
|
+
* Check for a $self.<assoc> in columns etc. - since the $self.<assoc> references the "outside" view
|
|
22
|
+
* of the association, this is not allowed.
|
|
23
|
+
*
|
|
24
|
+
* @param {string} queryPart Part of the query that is being checked
|
|
25
|
+
* @returns {Function} Function as callback for applyTransformations
|
|
26
|
+
*/
|
|
27
|
+
function checkRefForInvalid$Self(queryPart) {
|
|
28
|
+
const signalError = (error, parent, type) => {
|
|
29
|
+
if (queryPart === 'columns') {
|
|
30
|
+
error(null, parent.$path,
|
|
31
|
+
{ name: parent.ref[0], type },
|
|
32
|
+
'Select items starting with $(NAME) must not contain path steps of type $(TYPE)');
|
|
33
|
+
}
|
|
34
|
+
else if (queryPart === 'orderBy') {
|
|
35
|
+
error(null, parent.$path,
|
|
36
|
+
{ id: queryPart, type },
|
|
37
|
+
'Items of the $(ID)-clause must not contain path steps of type $(TYPE)');
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
error(null, parent.$path,
|
|
41
|
+
{ id: queryPart, name: parent.ref[0], type },
|
|
42
|
+
'Items of the $(ID)-clause starting with $(NAME) must not contain path steps of type $(TYPE)');
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
return function checkForInvalid$SelfInRef(parent) {
|
|
46
|
+
if (parent.ref && (parent.$scope === '$self' || parent.$scope === '$query')) {
|
|
47
|
+
const { _links } = parent;
|
|
48
|
+
for (let j = parent.$scope === '$self' ? 1 : 0; j < _links.length - 1; j++) {
|
|
49
|
+
if (_links[j].art.target) {
|
|
50
|
+
if (_links[j].art.on) {
|
|
51
|
+
// It's an unmanaged association - traversal is always forbidden
|
|
52
|
+
signalError(this.error, parent, _links[j].art.type);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// It's a managed association - access of the foreign keys is allowed
|
|
56
|
+
const nextRef = parent.ref[j + 1].id || parent.ref[j + 1];
|
|
57
|
+
if (!_links[j].art.keys.some(r => r.ref[0] === nextRef))
|
|
58
|
+
signalError(this.error, parent, _links[j].art.type);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const last = _links[_links.length - 1];
|
|
20
64
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
this.error(null, selectItem.$path,
|
|
26
|
-
{ name: selectItem.ref[0], type: pathStepWithTarget.art.type },
|
|
27
|
-
'Select items starting with $(NAME) must not contain path steps of type $(TYPE)');
|
|
65
|
+
if (last.art.target && last.art.on) {
|
|
66
|
+
// It's an unmanaged association - traversal is always forbidden
|
|
67
|
+
signalError(this.error, parent, last.art.type);
|
|
68
|
+
} // managed is okay, can be handled via tuple expansion
|
|
28
69
|
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Check the given assoc filter for usage of $self - in an assoc-filter, you must only
|
|
75
|
+
* address things on the target side of the association, not from global scope.
|
|
76
|
+
*
|
|
77
|
+
* @param {object} parent
|
|
78
|
+
* @param {string} prop
|
|
79
|
+
* @param {Array} where
|
|
80
|
+
*/
|
|
81
|
+
function checkFilterForInvalid$Self(parent, prop, where) {
|
|
82
|
+
where.forEach((whereStep) => {
|
|
83
|
+
if (whereStep.ref && ( whereStep.ref[0] === '$projection' || whereStep.ref[0] === '$self')) {
|
|
84
|
+
this.error('expr-where-unexpected-self', whereStep.$path,
|
|
85
|
+
{ name: whereStep.ref[0] },
|
|
86
|
+
'Path steps inside of filters must not start with $(NAME)');
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const aTCB = (parent, prop) => {
|
|
92
|
+
applyTransformationsOnNonDictionary(parent, prop, {
|
|
93
|
+
ref: checkRefForInvalid$Self(prop).bind(this),
|
|
94
|
+
where: checkFilterForInvalid$Self.bind(this),
|
|
95
|
+
}, { skipStandard: { on: true }, drillRef: true });
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const transformers = {
|
|
99
|
+
columns: aTCB,
|
|
100
|
+
groupBy: aTCB,
|
|
101
|
+
orderBy: aTCB,
|
|
102
|
+
having: aTCB,
|
|
103
|
+
where: aTCB,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
if (this.options.transformation === 'hdbcds') {
|
|
107
|
+
transformers.xpr = (parent) => {
|
|
108
|
+
if (parent.func) {
|
|
109
|
+
this.error(null, parent.$path,
|
|
110
|
+
'Window functions are not supported by SAP HANA CDS');
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
applyTransformationsOnNonDictionary(query, 'SELECT', transformers );
|
|
116
|
+
|
|
35
117
|
// .call() with 'this' to ensure we have access to the options
|
|
36
118
|
rejectManagedAssociationsAndStructuresForHdbcdsNames.call(this, SELECT, SELECT.$path);
|
|
37
119
|
}
|