@sap/cds-compiler 2.15.8 → 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 +102 -1590
- package/bin/.eslintrc.json +2 -1
- package/bin/cdsc.js +61 -46
- package/doc/API.md +11 -0
- package/doc/CHANGELOG_ARCHIVE.md +1592 -0
- package/doc/CHANGELOG_BETA.md +26 -5
- package/doc/CHANGELOG_DEPRECATED.md +55 -1
- package/doc/{DeprecatedOptions.md → DeprecatedOptions_v2.md} +3 -1
- package/doc/Versioning.md +20 -1
- package/lib/api/.eslintrc.json +2 -2
- package/lib/api/main.js +282 -156
- package/lib/api/options.js +17 -88
- package/lib/api/validate.js +6 -10
- package/lib/base/keywords.js +280 -110
- package/lib/base/message-registry.js +85 -25
- package/lib/base/messages.js +119 -89
- package/lib/base/model.js +46 -2
- package/lib/base/optionProcessorHelper.js +53 -21
- package/lib/checks/actionsFunctions.js +15 -12
- package/lib/checks/annotationsOData.js +1 -1
- package/lib/checks/cdsPersistence.js +1 -0
- package/lib/checks/elements.js +6 -6
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/nonexpandableStructured.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +2 -1
- package/lib/checks/selectItems.js +101 -15
- package/lib/checks/types.js +7 -8
- package/lib/checks/utils.js +2 -2
- package/lib/checks/validator.js +3 -3
- package/lib/compiler/assert-consistency.js +78 -21
- package/lib/compiler/base.js +6 -4
- package/lib/compiler/builtins.js +177 -10
- package/lib/compiler/checks.js +1 -1
- package/lib/compiler/define.js +28 -23
- package/lib/compiler/extend.js +75 -18
- package/lib/compiler/finalize-parse-cdl.js +25 -18
- package/lib/compiler/index.js +27 -11
- package/lib/compiler/moduleLayers.js +7 -0
- package/lib/compiler/populate.js +26 -39
- package/lib/compiler/propagator.js +12 -7
- package/lib/compiler/resolve.js +207 -236
- package/lib/compiler/shared.js +100 -93
- package/lib/compiler/tweak-assocs.js +13 -20
- package/lib/compiler/utils.js +20 -6
- package/lib/edm/annotations/preprocessAnnotations.js +12 -13
- package/lib/edm/csn2edm.js +35 -37
- package/lib/edm/edm.js +22 -13
- package/lib/edm/edmAnnoPreprocessor.js +349 -0
- package/lib/edm/edmInboundChecks.js +85 -0
- package/lib/edm/edmPreprocessor.js +338 -689
- package/lib/edm/edmUtils.js +97 -67
- package/lib/gen/Dictionary.json +29 -9
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +8 -31
- package/lib/gen/language.tokens +105 -114
- package/lib/gen/languageLexer.interp +1 -34
- package/lib/gen/languageLexer.js +892 -1007
- package/lib/gen/languageLexer.tokens +95 -106
- package/lib/gen/languageParser.js +20629 -22474
- 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 +74 -69
- package/lib/json/to-csn.js +17 -14
- package/lib/language/antlrParser.js +2 -2
- package/lib/language/docCommentParser.js +61 -38
- package/lib/language/errorStrategy.js +52 -40
- package/lib/language/genericAntlrParser.js +424 -292
- package/lib/language/language.g4 +604 -687
- package/lib/language/multiLineStringParser.js +14 -42
- package/lib/language/textUtils.js +44 -0
- package/lib/main.d.ts +28 -42
- package/lib/main.js +104 -81
- package/lib/model/api.js +1 -1
- package/lib/model/csnRefs.js +57 -30
- package/lib/model/csnUtils.js +189 -287
- package/lib/model/revealInternalProperties.js +32 -10
- package/lib/model/sortViews.js +32 -31
- package/lib/modelCompare/compare.js +3 -0
- package/lib/optionProcessor.js +91 -57
- package/lib/render/.eslintrc.json +1 -1
- package/lib/render/DuplicateChecker.js +4 -7
- package/lib/render/manageConstraints.js +70 -2
- package/lib/render/toCdl.js +387 -367
- package/lib/render/toHdbcds.js +20 -16
- package/lib/render/toRename.js +44 -22
- package/lib/render/toSql.js +81 -59
- package/lib/render/utils/common.js +16 -3
- package/lib/render/utils/sql.js +20 -19
- package/lib/sql-identifier.js +6 -0
- package/lib/transform/db/.eslintrc.json +3 -2
- package/lib/transform/db/associations.js +43 -35
- package/lib/transform/db/cdsPersistence.js +5 -16
- package/lib/transform/db/constraints.js +1 -1
- package/lib/transform/db/expansion.js +7 -6
- package/lib/transform/db/flattening.js +16 -18
- package/lib/transform/db/transformExists.js +7 -5
- package/lib/transform/db/views.js +3 -3
- package/lib/transform/draft/.eslintrc.json +2 -2
- package/lib/transform/draft/db.js +6 -6
- package/lib/transform/draft/odata.js +6 -7
- package/lib/transform/forHanaNew.js +30 -24
- package/lib/transform/forOdataNew.js +14 -16
- package/lib/transform/localized.js +35 -25
- package/lib/transform/odata/toFinalBaseType.js +10 -10
- package/lib/transform/odata/typesExposure.js +17 -8
- package/lib/transform/odata/utils.js +1 -38
- package/lib/transform/transformUtilsNew.js +63 -77
- package/lib/transform/translateAssocsToJoins.js +2 -2
- package/lib/transform/universalCsn/.eslintrc.json +2 -2
- package/lib/transform/universalCsn/coreComputed.js +11 -6
- package/lib/transform/universalCsn/universalCsnEnricher.js +33 -5
- package/lib/utils/file.js +31 -21
- package/lib/utils/moduleResolve.js +0 -1
- package/lib/utils/timetrace.js +20 -21
- package/package.json +34 -4
- package/share/messages/syntax-expected-integer.md +9 -8
- package/doc/ApiMigration.md +0 -237
- package/doc/CommandLineMigration.md +0 -58
- package/doc/ErrorMessages.md +0 -175
- package/doc/FioriAnnotations.md +0 -94
- package/doc/ODataTransformation.md +0 -273
- package/lib/backends.js +0 -529
- package/lib/checks/unknownMagic.js +0 -41
- package/lib/fix_antlr4-8_warning.js +0 -56
|
@@ -1,43 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
* @todo Combine with function from docCommentParser
|
|
10
|
-
* @param {string} str
|
|
11
|
-
* @returns {boolean}
|
|
12
|
-
*/
|
|
13
|
-
function isWhiteSpaceOnly(str) {
|
|
14
|
-
return /^\s*$/.test(str);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Check whether the given character is a white-space character as
|
|
19
|
-
* defined by §11.2 of the ECMAScript 2020 specification.
|
|
20
|
-
* See <https://262.ecma-international.org/11.0/#sec-white-space>.
|
|
21
|
-
*
|
|
22
|
-
* | Code Point | Name | Abbreviation |
|
|
23
|
-
* |:--------------------|:-----------------------------------------------|--------------|
|
|
24
|
-
* | U+0009 | CHARACTER TABULATION | `<TAB>` |
|
|
25
|
-
* | U+000B | LINE TABULATION | `<VT>` |
|
|
26
|
-
* | U+000C | FORM FEED (FF) | `<FF>` |
|
|
27
|
-
* | U+0020 | SPACE | `<SP>` |
|
|
28
|
-
* | U+00A0 | NO-BREAK SPACE | `<NBSP>` |
|
|
29
|
-
* | U+FEFF | ZERO WIDTH NO-BREAK SPACE | `<ZWNBSP>` |
|
|
30
|
-
* | Other category “Zs” | Any other Unicode “Space_Separator” code point | `<USP>` |
|
|
31
|
-
*
|
|
32
|
-
* @param char
|
|
33
|
-
* @returns {boolean}
|
|
34
|
-
*/
|
|
35
|
-
function isWhitespaceCharacter(char) {
|
|
36
|
-
return whitespaceRegEx.test(char);
|
|
37
|
-
}
|
|
3
|
+
const {
|
|
4
|
+
isWhitespaceOrNewLineOnly,
|
|
5
|
+
isWhitespaceCharacterNoNewline,
|
|
6
|
+
cdlNewLineRegEx,
|
|
7
|
+
} = require('./textUtils');
|
|
38
8
|
|
|
39
9
|
/**
|
|
40
10
|
* Strips and counts the indentation from the given string.
|
|
11
|
+
* This function is similar to the one in docCommentParser.js, but
|
|
12
|
+
* has special handling for the first and last line of the string.
|
|
41
13
|
*
|
|
42
14
|
* @example
|
|
43
15
|
* | hello
|
|
@@ -58,10 +30,10 @@ function stripIndentation(str) {
|
|
|
58
30
|
}
|
|
59
31
|
|
|
60
32
|
// Note: We have to check all newline characters, as the string is not normalized, yet.
|
|
61
|
-
const lines = str.split(
|
|
33
|
+
const lines = str.split(cdlNewLineRegEx);
|
|
62
34
|
const n = lines.length;
|
|
63
35
|
|
|
64
|
-
const hasTrailingLineBreak =
|
|
36
|
+
const hasTrailingLineBreak = cdlNewLineRegEx.test(str[str.length - 1]);
|
|
65
37
|
if (hasTrailingLineBreak) {
|
|
66
38
|
// Shortcut:
|
|
67
39
|
// If there is a trailing line break, it means that ``` is on newline and
|
|
@@ -73,12 +45,12 @@ function stripIndentation(str) {
|
|
|
73
45
|
const minIndent = lines.reduce((min, line, index) => {
|
|
74
46
|
// Note: Last line is the line containing ```. There, we always count the indentation,
|
|
75
47
|
// even if blank. For all other lines, blank lines are ignored.
|
|
76
|
-
if (
|
|
48
|
+
if (isWhitespaceOrNewLineOnly(line) && index !== (n-1))
|
|
77
49
|
return min;
|
|
78
50
|
|
|
79
51
|
let count = 0;
|
|
80
52
|
const length = Math.min(min, line.length);
|
|
81
|
-
while (count < length &&
|
|
53
|
+
while (count < length && isWhitespaceCharacterNoNewline(line[count])) {
|
|
82
54
|
count++;
|
|
83
55
|
}
|
|
84
56
|
return Math.min(min, count);
|
|
@@ -138,7 +110,7 @@ class MultiLineStringParser {
|
|
|
138
110
|
// If there are no line breaks, emit an error as normal single-back-tick
|
|
139
111
|
// strings should be used instead. Because the first line is skipped,
|
|
140
112
|
// there is no text without at least one line break.
|
|
141
|
-
if (!
|
|
113
|
+
if (!cdlNewLineRegEx.test(this.str)) {
|
|
142
114
|
const loc = this._locationForCharacters(this.end, 1);
|
|
143
115
|
this.parser.message('syntax-invalid-text-block', loc);
|
|
144
116
|
return '';
|
|
@@ -300,7 +272,7 @@ class MultiLineStringParser {
|
|
|
300
272
|
let codePoint = '';
|
|
301
273
|
|
|
302
274
|
for (let j = 0; j < count; ++j) {
|
|
303
|
-
if (!this._eos() && /^[
|
|
275
|
+
if (!this._eos() && /^[\dA-Fa-f]$/.test(this._lookahead())) {
|
|
304
276
|
this._move();
|
|
305
277
|
codePoint += this._current();
|
|
306
278
|
} else {
|
|
@@ -330,7 +302,7 @@ class MultiLineStringParser {
|
|
|
330
302
|
this._move(); // 'u'
|
|
331
303
|
|
|
332
304
|
while (!this._eos()) {
|
|
333
|
-
if (/^[
|
|
305
|
+
if (/^[\dA-Fa-f]$/.test(this._lookahead())) {
|
|
334
306
|
this._move();
|
|
335
307
|
codePoint += this._current();
|
|
336
308
|
} else if (this._lookahead() === '}') {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/** Whitespace characters without line-breaks. */
|
|
4
|
+
const whitespaceRegEx = /[\t\u{000B}\u{000C} \u{00A0}\u{FEFF}\p{Zs}]/u;
|
|
5
|
+
const cdlNewLineRegEx = /\r\n?|\n|\u2028|\u2029/u;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Returns true if the given string only contains whitespace characters.
|
|
9
|
+
* In contrast to `whitespaceRegEx`, it also matches newlines.
|
|
10
|
+
*
|
|
11
|
+
* @param {string} str
|
|
12
|
+
* @returns {boolean}
|
|
13
|
+
*/
|
|
14
|
+
function isWhitespaceOrNewLineOnly(str) {
|
|
15
|
+
return /^\s*$/.test(str);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Check whether the given character is a white-space character as
|
|
20
|
+
* defined by §11.2 of the ECMAScript 2020 specification.
|
|
21
|
+
* See <https://262.ecma-international.org/11.0/#sec-white-space>.
|
|
22
|
+
*
|
|
23
|
+
* | Code Point | Name | Abbreviation |
|
|
24
|
+
* |:--------------------|:-----------------------------------------------|--------------|
|
|
25
|
+
* | U+0009 | CHARACTER TABULATION | `<TAB>` |
|
|
26
|
+
* | U+000B | LINE TABULATION | `<VT>` |
|
|
27
|
+
* | U+000C | FORM FEED (FF) | `<FF>` |
|
|
28
|
+
* | U+0020 | SPACE | `<SP>` |
|
|
29
|
+
* | U+00A0 | NO-BREAK SPACE | `<NBSP>` |
|
|
30
|
+
* | U+FEFF | ZERO WIDTH NO-BREAK SPACE | `<ZWNBSP>` |
|
|
31
|
+
* | Other category “Zs” | Any other Unicode “Space_Separator” code point | `<USP>` |
|
|
32
|
+
*
|
|
33
|
+
* @param char
|
|
34
|
+
* @returns {boolean}
|
|
35
|
+
*/
|
|
36
|
+
function isWhitespaceCharacterNoNewline(char) {
|
|
37
|
+
return whitespaceRegEx.test(char);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
isWhitespaceOrNewLineOnly,
|
|
42
|
+
isWhitespaceCharacterNoNewline,
|
|
43
|
+
cdlNewLineRegEx,
|
|
44
|
+
};
|
package/lib/main.d.ts
CHANGED
|
@@ -86,6 +86,15 @@ declare namespace compiler {
|
|
|
86
86
|
* the prefix for SAP CDS packages / CDS files.
|
|
87
87
|
*/
|
|
88
88
|
cdsHome?: string
|
|
89
|
+
/**
|
|
90
|
+
* When set to `true`, and the model contains an entity `sap.common.Languages`
|
|
91
|
+
* with an element `code`, all generated texts entities additionally contain
|
|
92
|
+
* an element `language` which is an association to `sap.common.Languages`
|
|
93
|
+
* using element `locale`.
|
|
94
|
+
*
|
|
95
|
+
* @since v2.8.0
|
|
96
|
+
*/
|
|
97
|
+
addTextsLanguageAssoc?: boolean
|
|
89
98
|
/**
|
|
90
99
|
* Option for {@link compileSources}. If set, all objects inside the
|
|
91
100
|
* provided sources dictionary are interpreted as XSN structures instead
|
|
@@ -403,6 +412,10 @@ declare namespace compiler {
|
|
|
403
412
|
* It could also be a simple string, which is then considered to be the source
|
|
404
413
|
* text of a file named `<stdin>.cds`.
|
|
405
414
|
*
|
|
415
|
+
* This function uses the direct value of USINGs (in CSN `"requires"`) for its dependency graph,
|
|
416
|
+
* i.e. this function does not resolve USINGs. If a USING matches a key in sourcesDict,
|
|
417
|
+
* we assume that it depends on that file (/sourcesDict entry).
|
|
418
|
+
*
|
|
406
419
|
* See function {@link compile} for the meaning of the argument `options`. If there
|
|
407
420
|
* are parse or other compilation errors, throws an exception {@link CompilationError}
|
|
408
421
|
* containing a list of individual errors.
|
|
@@ -581,7 +594,6 @@ declare namespace compiler {
|
|
|
581
594
|
* coloring will be used. If 'auto', we will decide based on certain factors such
|
|
582
595
|
* as whether the shell is a TTY and whether the environment variable `NO_COLOR` is
|
|
583
596
|
* unset.
|
|
584
|
-
|
|
585
597
|
*/
|
|
586
598
|
export function messageContext(sourceLines: string[], msg: CompileMessage, config?: {
|
|
587
599
|
color?: boolean | 'auto'
|
|
@@ -608,25 +620,6 @@ declare namespace compiler {
|
|
|
608
620
|
*/
|
|
609
621
|
export function hasErrors(messages: CompileMessage[]): boolean;
|
|
610
622
|
|
|
611
|
-
/**
|
|
612
|
-
* Same as {@link to.edm} but expects a {@link for.odata} transformed CSN.
|
|
613
|
-
*
|
|
614
|
-
* Note that parameter `service` is the same as `ODataOptions.service`.
|
|
615
|
-
* The latter is not used. OData specific options have an internal format.
|
|
616
|
-
*
|
|
617
|
-
* @deprecated Use {@link to.edm} instead. If it detects a pre-transformed CSN, it won't run for.odata().
|
|
618
|
-
*/
|
|
619
|
-
export function preparedCsnToEdm(csn: CSN, service: string, options: ODataOptions): object;
|
|
620
|
-
/**
|
|
621
|
-
* Same as {@link to.edm} but expects a {@link for.odata} transformed CSN.
|
|
622
|
-
*
|
|
623
|
-
* Note that parameter `service` is the same as `ODataOptions.service`.
|
|
624
|
-
* The latter is not used. OData specific options have an outdated format.
|
|
625
|
-
*
|
|
626
|
-
* @deprecated Use {@link to.edmx} instead. If it detects a pre-transformed CSN, it won't run for.odata().
|
|
627
|
-
*/
|
|
628
|
-
export function preparedCsnToEdmx(csn: CSN, service: string, options: ODataOptions): string;
|
|
629
|
-
|
|
630
623
|
export namespace parse {
|
|
631
624
|
/**
|
|
632
625
|
* Parse the given CDL in parseCdl mode and return its corresponding CSN representation.
|
|
@@ -658,15 +651,6 @@ declare namespace compiler {
|
|
|
658
651
|
function expr(cdl: string, filename?: string, options?: Options): CXN;
|
|
659
652
|
}
|
|
660
653
|
|
|
661
|
-
/**
|
|
662
|
-
* @deprecated Use {@link parse.cql} instead.
|
|
663
|
-
*/
|
|
664
|
-
export function parseToCqn(cql: string, filename?: string, options?: Options): CQN;
|
|
665
|
-
/**
|
|
666
|
-
* @deprecated Use {@link parse.expr} instead.
|
|
667
|
-
*/
|
|
668
|
-
export function parseToExpr(expr: string, filename?: string, options?: Options): CXN;
|
|
669
|
-
|
|
670
654
|
/**
|
|
671
655
|
* @note Actual name is "for" which can't be used directly in the documentation
|
|
672
656
|
* as it is a reserved name in TypeScript.
|
|
@@ -812,7 +796,7 @@ declare namespace compiler {
|
|
|
812
796
|
/**
|
|
813
797
|
* Rendered csn.namespace property + using directives.
|
|
814
798
|
*/
|
|
815
|
-
|
|
799
|
+
namespace?: string
|
|
816
800
|
}
|
|
817
801
|
|
|
818
802
|
/**
|
|
@@ -857,20 +841,17 @@ declare namespace compiler {
|
|
|
857
841
|
* - For the 'plain' naming mode, it means converting all `.` to `_` and upper-casing.
|
|
858
842
|
* - For the 'quoted' naming mode, this means correctly replacing some `.` with `_`.
|
|
859
843
|
*
|
|
844
|
+
* The above rules might differ for different SQL dialects.
|
|
845
|
+
* Exceptions will be listed below.
|
|
846
|
+
*
|
|
860
847
|
* @param artifactName The fully qualified name of the artifact
|
|
861
848
|
* @param sqlMapping The naming mode to use. See {@link SqlOptions.sqlMapping} for more details.
|
|
862
849
|
* @param csn
|
|
850
|
+
* @param sqlDialect The SQL dialect to use. See {@link SqlOptions.sqlDialect} for more details.
|
|
863
851
|
* @returns {string} The resulting database name for (absolute) 'artifactName', depending on the current naming mode.
|
|
864
852
|
* @since v2.1.0
|
|
865
853
|
*/
|
|
866
|
-
export function getArtifactCdsPersistenceName(artifactName: string, sqlMapping: string, csn: CSN): string;
|
|
867
|
-
/**
|
|
868
|
-
* This is an old function signature. If it is used - with a namespace as the third argument - the result might be wrong,
|
|
869
|
-
* since the `.` -> `_` conversion for 'quoted'/'hdbcds' is missing.
|
|
870
|
-
*
|
|
871
|
-
* @deprecated Use the other overload with CSN instead.
|
|
872
|
-
*/
|
|
873
|
-
export function getArtifactCdsPersistenceName(artifactName: string, sqlMapping: string, namespace: string): string;
|
|
854
|
+
export function getArtifactCdsPersistenceName(artifactName: string, sqlMapping: string, csn: CSN, sqlDialect: string): string;
|
|
874
855
|
/**
|
|
875
856
|
* Return the resulting database element name for `elemName`, depending on the current
|
|
876
857
|
* naming mode.
|
|
@@ -879,11 +860,15 @@ declare namespace compiler {
|
|
|
879
860
|
* - For the 'quoted' naming mode, it means converting all `.` to `_`.
|
|
880
861
|
* No other naming modes are accepted!
|
|
881
862
|
*
|
|
863
|
+
* The above rules might differ for different SQL dialects.
|
|
864
|
+
* Exceptions will be listed below.
|
|
865
|
+
*
|
|
882
866
|
* @param elemName The name of the element. For structured elements, concat by dot, e.g. `sub.elem`.
|
|
883
867
|
* @param sqlMapping The naming mode to use. See {@link SqlOptions.sqlMapping} for more details.
|
|
868
|
+
* @param sqlDialect The SQL dialect to use. See {@link SqlOptions.sqlDialect} for more details.
|
|
884
869
|
* @returns The resulting database element name for 'elemName', depending on the current naming mode.
|
|
885
870
|
*/
|
|
886
|
-
export function getElementCdsPersistenceName(elemName: string, sqlMapping: string): string;
|
|
871
|
+
export function getElementCdsPersistenceName(elemName: string, sqlMapping: string, sqlDialect: string): string;
|
|
887
872
|
|
|
888
873
|
/**
|
|
889
874
|
* Traverse the CSN node `csn`.
|
|
@@ -911,6 +896,7 @@ declare namespace compiler {
|
|
|
911
896
|
* but not `cds.foundation.*`.
|
|
912
897
|
*
|
|
913
898
|
* @param definitionName Top-level definition name of the artifact.
|
|
899
|
+
* @since v2.14.0
|
|
914
900
|
*/
|
|
915
901
|
function isInReservedNamespace(definitionName: string): boolean;
|
|
916
902
|
}
|
|
@@ -1003,7 +989,7 @@ declare namespace compiler {
|
|
|
1003
989
|
}
|
|
1004
990
|
}
|
|
1005
991
|
/**
|
|
1006
|
-
* String representation of the message.
|
|
992
|
+
* String representation of the message. It may be a multi-line message in the future.
|
|
1007
993
|
*/
|
|
1008
994
|
message: string
|
|
1009
995
|
/**
|
|
@@ -1022,7 +1008,7 @@ declare namespace compiler {
|
|
|
1022
1008
|
*/
|
|
1023
1009
|
error?: Error
|
|
1024
1010
|
/**
|
|
1025
|
-
* Returns a human
|
|
1011
|
+
* Returns a human-readable string of the compiler message. Uses {@link messageString} to render
|
|
1026
1012
|
* the message without filename normalization and without a message ID.
|
|
1027
1013
|
*/
|
|
1028
1014
|
toString(): string;
|
|
@@ -1054,7 +1040,7 @@ declare namespace compiler {
|
|
|
1054
1040
|
* - `false`: the file does not exist
|
|
1055
1041
|
* - `true`: file exists (fstat), no further knowledge yet - i.e. value will change!
|
|
1056
1042
|
* - `string` or `Buffer`: the file content
|
|
1057
|
-
* - `{ realname: fs.realpath(filename) }`: if filename is not canonicalized
|
|
1043
|
+
* - `{ realname: fs.realpath.native(filename) }`: if filename is not canonicalized
|
|
1058
1044
|
*/
|
|
1059
1045
|
export type FileCache = Record<string, boolean | string | Buffer | { realname: string }>;
|
|
1060
1046
|
|
package/lib/main.js
CHANGED
|
@@ -13,70 +13,59 @@
|
|
|
13
13
|
|
|
14
14
|
'use strict';
|
|
15
15
|
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const finalizeParseCdl = require('./compiler/finalize-parse-cdl');
|
|
16
|
+
const snapi = lazyload('./api/main');
|
|
17
|
+
const csnUtils = lazyload('./model/csnUtils');
|
|
18
|
+
const model_api = lazyload('./model/api');
|
|
19
|
+
const messages = lazyload('./base/messages');
|
|
20
|
+
const sqlIdentifier = lazyload('./sql-identifier');
|
|
21
|
+
const keywords = lazyload( './base/keywords' );
|
|
22
|
+
|
|
23
|
+
const parseLanguage = lazyload('./language/antlrParser');
|
|
24
|
+
const compiler = lazyload('./compiler');
|
|
25
|
+
const shared = lazyload('./compiler/shared');
|
|
26
|
+
const define = lazyload('./compiler/define');
|
|
27
|
+
const builtins = lazyload("./compiler/builtins");
|
|
28
|
+
const finalizeParseCdl = lazyload('./compiler/finalize-parse-cdl');
|
|
30
29
|
|
|
31
30
|
// The compiler version (taken from package.json)
|
|
32
31
|
function version() {
|
|
33
32
|
return require('../package.json').version;
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
const
|
|
37
|
-
CompilationError,
|
|
38
|
-
messageString,
|
|
39
|
-
messageStringMultiline,
|
|
40
|
-
messageContext,
|
|
41
|
-
hasErrors,
|
|
42
|
-
explainMessage,
|
|
43
|
-
hasMessageExplanation
|
|
44
|
-
} = require('./base/messages');
|
|
45
|
-
|
|
46
|
-
const { compactModel, compactQuery, compactExpr } = require('./json/to-csn')
|
|
35
|
+
const toCsn = lazyload('./json/to-csn')
|
|
47
36
|
|
|
48
37
|
function parseCdl( cdlSource, filename, options = {} ) {
|
|
49
38
|
options = Object.assign( {}, options, { parseCdl: true } );
|
|
50
39
|
const sources = Object.create(null);
|
|
51
40
|
/** @type {XSN.Model} */
|
|
52
41
|
const model = { sources, options, $functions: {}, $volatileFunctions: {} };
|
|
53
|
-
const messageFunctions = createMessageFunctions( options, 'parse', model );
|
|
42
|
+
const messageFunctions = messages.createMessageFunctions( options, 'parse', model );
|
|
54
43
|
model.$messageFunctions = messageFunctions;
|
|
55
44
|
|
|
56
45
|
const xsn = parseLanguage( cdlSource, filename, Object.assign( { parseOnly: true }, options ),
|
|
57
46
|
messageFunctions );
|
|
58
47
|
sources[filename] = xsn;
|
|
59
|
-
fns( model );
|
|
48
|
+
shared.fns( model );
|
|
60
49
|
define( model );
|
|
61
50
|
finalizeParseCdl( model );
|
|
62
51
|
messageFunctions.throwWithError();
|
|
63
|
-
return compactModel( model );
|
|
52
|
+
return toCsn.compactModel( model );
|
|
64
53
|
}
|
|
65
54
|
|
|
66
55
|
function parseCql( cdlSource, filename = '<query>.cds', options = {} ) {
|
|
67
|
-
const messageFunctions = createMessageFunctions( options, 'parse' );
|
|
56
|
+
const messageFunctions = messages.createMessageFunctions( options, 'parse' );
|
|
68
57
|
const xsn = parseLanguage( cdlSource, filename, Object.assign( { parseOnly: true }, options ),
|
|
69
58
|
messageFunctions, 'query' );
|
|
70
59
|
messageFunctions.throwWithError();
|
|
71
|
-
return compactQuery( xsn );
|
|
60
|
+
return toCsn.compactQuery( xsn );
|
|
72
61
|
}
|
|
73
62
|
|
|
74
63
|
function parseExpr( cdlSource, filename = '<expr>.cds', options = {} ) {
|
|
75
|
-
const messageFunctions = createMessageFunctions( options, 'parse' );
|
|
64
|
+
const messageFunctions = messages.createMessageFunctions( options, 'parse' );
|
|
76
65
|
const xsn = parseLanguage( cdlSource, filename, Object.assign( { parseOnly: true }, options ),
|
|
77
66
|
messageFunctions, 'expr' );
|
|
78
67
|
messageFunctions.throwWithError();
|
|
79
|
-
return compactExpr( xsn );
|
|
68
|
+
return toCsn.compactExpr( xsn );
|
|
80
69
|
}
|
|
81
70
|
|
|
82
71
|
// FIXME: The implementation of those functions that delegate to 'backends' should probably move here
|
|
@@ -84,74 +73,108 @@ function parseExpr( cdlSource, filename = '<expr>.cds', options = {} ) {
|
|
|
84
73
|
module.exports = {
|
|
85
74
|
// Compiler
|
|
86
75
|
version,
|
|
87
|
-
compile: (...args) => compileX(...args).then( compactModel ), // main function
|
|
88
|
-
compileSync: (filenames, dir, options, fileCache) => compactModel( compileSyncX(filenames, dir, options, fileCache) ), // main function
|
|
89
|
-
compileSources: (sourcesDict, options) => compactModel( compileSourcesX(sourcesDict, options) ), // main function
|
|
76
|
+
compile: (...args) => compiler.compileX(...args).then( toCsn.compactModel ), // main function
|
|
77
|
+
compileSync: (filenames, dir, options, fileCache) => toCsn.compactModel( compiler.compileSyncX(filenames, dir, options, fileCache) ), // main function
|
|
78
|
+
compileSources: (sourcesDict, options) => toCsn.compactModel( compiler.compileSourcesX(sourcesDict, options) ), // main function
|
|
90
79
|
compactModel: csn => csn, // for easy v2 migration
|
|
91
|
-
CompilationError
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
80
|
+
get CompilationError() {
|
|
81
|
+
Object.defineProperty(this, "CompilationError", {
|
|
82
|
+
value: messages.CompilationError,
|
|
83
|
+
writable: false,
|
|
84
|
+
configurable: false,
|
|
85
|
+
enumerable: false
|
|
86
|
+
});
|
|
87
|
+
return messages.CompilationError;
|
|
88
|
+
},
|
|
89
|
+
sortMessages: (...args) => messages.sortMessages(...args),
|
|
90
|
+
sortMessagesSeverityAware: (...args) => messages.sortMessagesSeverityAware(...args),
|
|
91
|
+
deduplicateMessages: (...args) => messages.deduplicateMessages(...args),
|
|
92
|
+
messageString: (...args) => messages.messageString(...args),
|
|
93
|
+
messageStringMultiline: (...args) => messages.messageStringMultiline(...args),
|
|
94
|
+
messageContext: (...args) => messages.messageContext(...args),
|
|
95
|
+
explainMessage: (...args) => messages.explainMessage(...args),
|
|
96
|
+
hasMessageExplanation: (...args) => messages.hasMessageExplanation(...args),
|
|
97
|
+
get InvocationError() {
|
|
98
|
+
Object.defineProperty(this, "InvocationError", {
|
|
99
|
+
value: compiler.InvocationError,
|
|
100
|
+
writable: false,
|
|
101
|
+
configurable: false,
|
|
102
|
+
enumerable: false
|
|
103
|
+
});
|
|
104
|
+
return compiler.InvocationError;
|
|
105
|
+
},
|
|
106
|
+
hasErrors: (...args) => messages.hasErrors(...args),
|
|
108
107
|
|
|
109
108
|
// additional API:
|
|
110
|
-
parse: { cdl: parseCdl, cql: parseCql, expr: parseExpr },
|
|
111
|
-
/**
|
|
112
|
-
* @deprecated Use parse.cql instead
|
|
113
|
-
*/
|
|
114
|
-
parseToCqn: parseCql,
|
|
115
|
-
/**
|
|
116
|
-
* @deprecated Use parse.expr instead
|
|
117
|
-
*/
|
|
118
|
-
parseToExpr: parseExpr, // deprecated name
|
|
109
|
+
parse: { cdl: (...args) => parseCdl(...args), cql: (...args) => parseCql(...args), expr: (...args) => parseExpr(...args) },
|
|
119
110
|
// SNAPI
|
|
120
|
-
for: { odata },
|
|
111
|
+
for: { odata: (...args) => snapi.odata(...args) },
|
|
121
112
|
to: {
|
|
122
|
-
cdl: Object.assign(cdl, {
|
|
123
|
-
keywords: Object.freeze([ ...keywords.cdl ]),
|
|
124
|
-
functions: Object.freeze([ ...keywords.cdl_functions ]),
|
|
113
|
+
cdl: Object.assign((...args) => snapi.cdl(...args), {
|
|
114
|
+
keywords: Object.freeze([ ...keywords.cdl ] ),
|
|
115
|
+
functions: Object.freeze([ ...keywords.cdl_functions ] ),
|
|
116
|
+
}),
|
|
117
|
+
sql: Object.assign((...args) => snapi.sql(...args), {
|
|
118
|
+
sqlite: {
|
|
119
|
+
keywords: Object.freeze([ ...keywords.sqlite ] )
|
|
120
|
+
},
|
|
121
|
+
smartId: (...args) => sqlIdentifier.smartId(...args),
|
|
122
|
+
smartFunctionId: (...args) => sqlIdentifier.smartFuncId(...args),
|
|
123
|
+
delimitedId: (...args) => sqlIdentifier.delimitedId(...args),
|
|
125
124
|
}),
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
smartFunctionId: smartFuncId,
|
|
130
|
-
delimitedId,
|
|
125
|
+
hdi: Object.assign((...args) => snapi.hdi(...args), {
|
|
126
|
+
migration: (...args) => snapi.hdi.migration(...args),
|
|
127
|
+
keywords: Object.freeze([ ...keywords.hana ] ),
|
|
131
128
|
}),
|
|
132
|
-
|
|
133
|
-
keywords: Object.freeze([ ...keywords.
|
|
129
|
+
hdbcds: Object.assign((...args) => snapi.hdbcds(...args), {
|
|
130
|
+
keywords: Object.freeze([ ...keywords.hdbcds ] ),
|
|
134
131
|
}),
|
|
135
|
-
|
|
136
|
-
|
|
132
|
+
edm: Object.assign((...args) => snapi.edm(...args), {
|
|
133
|
+
all: (...args) => snapi.edm.all(...args)
|
|
134
|
+
}),
|
|
135
|
+
edmx: Object.assign((...args) => snapi.edmx(...args), {
|
|
136
|
+
all: (...args) => snapi.edmx.all(...args)
|
|
137
137
|
}),
|
|
138
|
-
edm,
|
|
139
|
-
edmx
|
|
140
138
|
},
|
|
141
139
|
// Convenience for hdbtabledata calculation in @sap/cds
|
|
142
|
-
getArtifactCdsPersistenceName: getArtifactDatabaseNameOf,
|
|
143
|
-
getElementCdsPersistenceName: getElementDatabaseNameOf,
|
|
140
|
+
getArtifactCdsPersistenceName: (...args) => csnUtils.getArtifactDatabaseNameOf(...args),
|
|
141
|
+
getElementCdsPersistenceName: (...args) => csnUtils.getElementDatabaseNameOf(...args),
|
|
144
142
|
|
|
145
143
|
// Other API functions:
|
|
146
|
-
traverseCsn,
|
|
144
|
+
traverseCsn: (...args) => model_api.traverseCsn(...args),
|
|
147
145
|
|
|
148
146
|
// INTERNAL functions for the cds-lsp package and friends - before you use
|
|
149
147
|
// it, you MUST talk with us - there can be potential incompatibilities with
|
|
150
148
|
// new releases (even having the same major version):
|
|
151
|
-
$lsp: { parse: parseX, compile: compileX, getArtifactName: a => a.name },
|
|
149
|
+
$lsp: { parse: (...args) => compiler.parseX(...args), compile: (...args) => compiler.compileX(...args), getArtifactName: a => a.name },
|
|
152
150
|
|
|
153
151
|
// CSN Model related functionality
|
|
154
152
|
model: {
|
|
155
|
-
isInReservedNamespace,
|
|
153
|
+
isInReservedNamespace: (...args) => builtins.isInReservedNamespace(...args),
|
|
156
154
|
},
|
|
157
155
|
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Load the module on-demand and not immediately.
|
|
159
|
+
*
|
|
160
|
+
* @param {string} moduleName Name of the module to load - like with require
|
|
161
|
+
* @returns {object} A Proxy that handles the on-demand loading
|
|
162
|
+
*/
|
|
163
|
+
function lazyload(moduleName) {
|
|
164
|
+
let module;
|
|
165
|
+
return new Proxy(((...args) => {
|
|
166
|
+
if (!module) // eslint-disable-next-line global-require
|
|
167
|
+
module = require(moduleName);
|
|
168
|
+
|
|
169
|
+
if (module.apply && typeof module.apply === 'function')
|
|
170
|
+
return module.apply(this, args);
|
|
171
|
+
return module; // for destructured calls
|
|
172
|
+
}), {
|
|
173
|
+
get(target, name) {
|
|
174
|
+
if (!module) // eslint-disable-next-line global-require
|
|
175
|
+
module = require(moduleName);
|
|
176
|
+
|
|
177
|
+
return module[name];
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
}
|
package/lib/model/api.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* Each function in `userFunctions` and `defaultFunctions` is called with:
|
|
12
12
|
* - `userFunctions`
|
|
13
13
|
* - the current CSN node, i.e. ‹parent node›.‹property name›
|
|
14
|
-
* - the
|
|
14
|
+
* - the ‹parent node›
|
|
15
15
|
* - the ‹property name› (might be useful if the same function is used for several props)
|
|
16
16
|
*/
|
|
17
17
|
const defaultFunctions = {
|