@sap/cds-compiler 2.13.8 → 3.0.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.
Files changed (127) hide show
  1. package/CHANGELOG.md +155 -1594
  2. package/bin/cdsc.js +144 -66
  3. package/doc/CHANGELOG_ARCHIVE.md +1592 -0
  4. package/doc/CHANGELOG_BETA.md +3 -4
  5. package/doc/CHANGELOG_DEPRECATED.md +35 -1
  6. package/doc/{DeprecatedOptions.md → DeprecatedOptions_v2.md} +3 -1
  7. package/doc/Versioning.md +20 -1
  8. package/lib/api/.eslintrc.json +2 -2
  9. package/lib/api/main.js +237 -122
  10. package/lib/api/options.js +17 -88
  11. package/lib/api/validate.js +12 -16
  12. package/lib/base/keywords.js +216 -109
  13. package/lib/base/message-registry.js +152 -37
  14. package/lib/base/messages.js +145 -83
  15. package/lib/base/model.js +44 -2
  16. package/lib/base/optionProcessorHelper.js +19 -0
  17. package/lib/checks/actionsFunctions.js +7 -5
  18. package/lib/checks/annotationsOData.js +11 -32
  19. package/lib/checks/arrayOfs.js +1 -34
  20. package/lib/checks/cdsPersistence.js +1 -0
  21. package/lib/checks/elements.js +6 -6
  22. package/lib/checks/invalidTarget.js +1 -1
  23. package/lib/checks/nonexpandableStructured.js +1 -1
  24. package/lib/checks/queryNoDbArtifacts.js +2 -1
  25. package/lib/checks/selectItems.js +5 -1
  26. package/lib/checks/types.js +4 -2
  27. package/lib/checks/utils.js +2 -2
  28. package/lib/checks/validator.js +4 -5
  29. package/lib/compiler/assert-consistency.js +16 -10
  30. package/lib/compiler/base.js +1 -0
  31. package/lib/compiler/builtins.js +98 -9
  32. package/lib/compiler/checks.js +22 -70
  33. package/lib/compiler/define.js +61 -13
  34. package/lib/compiler/extend.js +79 -14
  35. package/lib/compiler/finalize-parse-cdl.js +46 -29
  36. package/lib/compiler/index.js +100 -37
  37. package/lib/compiler/moduleLayers.js +7 -0
  38. package/lib/compiler/populate.js +19 -18
  39. package/lib/compiler/propagator.js +7 -4
  40. package/lib/compiler/resolve.js +297 -234
  41. package/lib/compiler/shared.js +107 -102
  42. package/lib/compiler/tweak-assocs.js +16 -11
  43. package/lib/compiler/utils.js +5 -0
  44. package/lib/edm/annotations/genericTranslation.js +93 -21
  45. package/lib/edm/csn2edm.js +230 -115
  46. package/lib/edm/edm.js +305 -226
  47. package/lib/edm/edmPreprocessor.js +509 -438
  48. package/lib/edm/edmUtils.js +31 -45
  49. package/lib/gen/Dictionary.json +98 -22
  50. package/lib/gen/language.checksum +1 -1
  51. package/lib/gen/language.interp +10 -30
  52. package/lib/gen/language.tokens +105 -114
  53. package/lib/gen/languageLexer.interp +1 -34
  54. package/lib/gen/languageLexer.js +889 -1007
  55. package/lib/gen/languageLexer.tokens +95 -106
  56. package/lib/gen/languageParser.js +20786 -22199
  57. package/lib/json/csnVersion.js +10 -11
  58. package/lib/json/from-csn.js +59 -51
  59. package/lib/json/to-csn.js +10 -10
  60. package/lib/language/antlrParser.js +2 -2
  61. package/lib/language/docCommentParser.js +62 -39
  62. package/lib/language/errorStrategy.js +52 -40
  63. package/lib/language/genericAntlrParser.js +348 -229
  64. package/lib/language/language.g4 +629 -653
  65. package/lib/language/multiLineStringParser.js +14 -42
  66. package/lib/language/textUtils.js +44 -0
  67. package/lib/main.d.ts +46 -43
  68. package/lib/main.js +108 -79
  69. package/lib/model/csnRefs.js +34 -7
  70. package/lib/model/csnUtils.js +337 -332
  71. package/lib/model/enrichCsn.js +1 -0
  72. package/lib/model/revealInternalProperties.js +30 -10
  73. package/lib/model/sortViews.js +32 -31
  74. package/lib/modelCompare/compare.js +6 -6
  75. package/lib/optionProcessor.js +73 -46
  76. package/lib/render/.eslintrc.json +1 -1
  77. package/lib/render/DuplicateChecker.js +4 -7
  78. package/lib/render/manageConstraints.js +70 -2
  79. package/lib/render/toCdl.js +1042 -882
  80. package/lib/render/toHdbcds.js +195 -245
  81. package/lib/render/toRename.js +44 -22
  82. package/lib/render/toSql.js +225 -241
  83. package/lib/render/utils/common.js +145 -15
  84. package/lib/render/utils/sql.js +20 -19
  85. package/lib/sql-identifier.js +6 -0
  86. package/lib/transform/db/.eslintrc.json +4 -3
  87. package/lib/transform/db/associations.js +2 -2
  88. package/lib/transform/db/cdsPersistence.js +5 -15
  89. package/lib/transform/db/constraints.js +4 -2
  90. package/lib/transform/db/expansion.js +22 -16
  91. package/lib/transform/db/flattening.js +109 -80
  92. package/lib/transform/db/transformExists.js +7 -7
  93. package/lib/transform/db/views.js +9 -6
  94. package/lib/transform/draft/.eslintrc.json +2 -2
  95. package/lib/transform/draft/db.js +6 -6
  96. package/lib/transform/draft/odata.js +6 -7
  97. package/lib/transform/forHanaNew.js +62 -48
  98. package/lib/transform/forOdataNew.js +49 -50
  99. package/lib/transform/localized.js +31 -20
  100. package/lib/transform/odata/toFinalBaseType.js +16 -14
  101. package/lib/transform/odata/typesExposure.js +146 -198
  102. package/lib/transform/odata/utils.js +1 -38
  103. package/lib/transform/transformUtilsNew.js +67 -84
  104. package/lib/transform/translateAssocsToJoins.js +7 -3
  105. package/lib/transform/universalCsn/.eslintrc.json +2 -2
  106. package/lib/transform/universalCsn/coreComputed.js +16 -9
  107. package/lib/transform/universalCsn/universalCsnEnricher.js +60 -10
  108. package/lib/utils/file.js +3 -3
  109. package/lib/utils/moduleResolve.js +13 -6
  110. package/lib/utils/timetrace.js +20 -21
  111. package/package.json +35 -4
  112. package/share/messages/message-explanations.json +2 -1
  113. package/share/messages/syntax-expected-integer.md +37 -0
  114. package/doc/ApiMigration.md +0 -237
  115. package/doc/CommandLineMigration.md +0 -58
  116. package/doc/ErrorMessages.md +0 -175
  117. package/doc/FioriAnnotations.md +0 -94
  118. package/doc/ODataTransformation.md +0 -273
  119. package/lib/backends.js +0 -529
  120. package/lib/fix_antlr4-8_warning.js +0 -56
  121. package/lib/transform/odata/attachPath.js +0 -96
  122. package/lib/transform/odata/expandStructKeysInAssociations.js +0 -59
  123. package/lib/transform/odata/generateForeignKeyElements.js +0 -261
  124. package/lib/transform/odata/referenceFlattener.js +0 -296
  125. package/lib/transform/odata/sortByAssociationDependency.js +0 -105
  126. package/lib/transform/odata/structuralPath.js +0 -72
  127. package/lib/transform/odata/structureFlattener.js +0 -171
@@ -1,105 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * In the OData transformer, managed associations produce foreign keys.
5
- * If an association is also a primary key, the additionally created foreign keys become also primary keys in the parent artifact.
6
- * Associations with partial foreign keys force other non-key elements and associations to become virtual primary keys.
7
- * Proper FK generation requires specific order of performing that.
8
- * This module provides functionality to sort managed associations according to their dependencies.
9
- */
10
-
11
- const {
12
- forEachDefinition,
13
- forEachMemberRecursively
14
- } = require('../../model/csnUtils');
15
-
16
- const {
17
- isAssociationOrComposition
18
- } = require('./utils');
19
- const { forEach } = require('../../utils/objectUtils.js');
20
-
21
- function buildDependenciesFor(csn, referenceFlattener, isExternalServiceMember) {
22
-
23
- let dependencies = {};
24
- forEachDefinition(csn, (def, definitionName) => {
25
- /** @type {CSN.Path} */
26
- let root = ['definitions', definitionName];
27
- forEachMemberRecursively(def, (element, elementName, structuralNodeName, subpath, parent) => {
28
- let path = root.concat(subpath);
29
- // go only through managed associations and compositions
30
- if (isAssociationOrComposition(element) && element.keys && !element.on) { // check association FKs
31
- let elementDependencies = []
32
- element.keys.forEach(iForeignKey => {
33
- let paths = iForeignKey.$paths;
34
- if (!paths) return; // invalid references can not be resolved thus no $paths -> test/odataTransformation/negative/ForeignKeys.cds
35
- let targetElementPath = paths[paths.length - 1];
36
- if (!targetElementPath) return; // TODO check why
37
- let targetElement = getElementForPath(csn, targetElementPath);
38
- if (!targetElement) { // element was moved
39
- targetElementPath = referenceFlattener.getElementTransition(targetElementPath);
40
- if (!targetElementPath) return; // TODO check why
41
- targetElement = getElementForPath(csn, targetElementPath);
42
- }
43
- if (targetElement && isAssociationOrComposition(targetElement)) {
44
- elementDependencies.push(targetElementPath);
45
- }
46
- })
47
- dependencies[path.join("/")] = { structuralNodeName, definitionName, elementName, element, path, parent, dependencies: elementDependencies };
48
- }
49
- }) // forEachMemberRecursively
50
- }, { skipArtifact: isExternalServiceMember }) // forEachDefinition
51
-
52
- let result = []; // final list of sorted association items
53
- let inResult = {}; // paths of associations which were added in the result
54
- let maxLoops = Object.keys(dependencies).length;
55
- let loops = 0;
56
- let done = false;
57
- // walk over all dependencies and add to the result if all dependents are already in the result
58
- while (!done) {
59
- if (loops > maxLoops) {
60
- throw Error('Failed to process the association dependencies - max loops reached');
61
- }
62
- done = true;
63
- let toDelete = [];
64
- forEach(dependencies, (name, item) => {
65
- let countOfUnprocessedDependents = 0;
66
- item.dependencies.forEach(path => {
67
- let spath = path.join('/');
68
- if (!inResult[spath]) countOfUnprocessedDependents++;
69
- })
70
- if (countOfUnprocessedDependents === 0) { // all dependents processed?
71
- let spath = item.path.join('/');
72
- if (!inResult[spath]) {
73
- inResult[spath] = true;
74
- result.push(item);
75
- }
76
- toDelete.push(name); // mark association to be removed from the processing list
77
- } else {
78
- done = false;
79
- }
80
- })
81
- // delete already processed associations
82
- toDelete.forEach(name => {
83
- delete dependencies[name];
84
- });
85
- loops++;
86
- } // while not done
87
-
88
- // check if all dependencies were processed
89
- if (Object.keys(dependencies).length !== 0) {
90
- throw Error('Failed to process the association dependencies - there are more dependencies left');
91
- }
92
- return result;
93
-
94
- function getElementForPath(node, path) {
95
- path.forEach(name => {
96
- if (!node) return;
97
- node = node[name];
98
- })
99
- return node;
100
- }
101
-
102
- }
103
-
104
- module.exports = buildDependenciesFor
105
-
@@ -1,72 +0,0 @@
1
- // The module traverses a given CSN using a specific path, collects structural node names and returns them.
2
-
3
- const structuralNodeHandlers = {
4
- definitions: traverseDict,
5
- elements: traverseDict,
6
- actions: traverseDict,
7
- params: traverseDict,
8
- items: traverseTyped,
9
- enum: traverseDict,
10
- returns: traverseTyped,
11
- on: traverseArray,
12
- keys: traverseArray,
13
- ref: traverseArray,
14
- query: traverseTyped,
15
- SELECT: traverseTyped,
16
- SET: traverseTyped,
17
- args: traverseArray,
18
- columns: traverseArray,
19
- projection: traverseTyped,
20
- from: traverseTyped,
21
- mixin: traverseDict,
22
- where: traverseArray,
23
- orderBy: traverseArray,
24
- groupBy: traverseArray,
25
- having: traverseArray,
26
- xpr: traverseArray,
27
- expand: traverseArray,
28
- inline: traverseArray,
29
- cast: traverseTyped,
30
- }
31
-
32
- function structuralPath(csn, path) {
33
- return traverseDict(csn.definitions, path, 1, ['definitions']);
34
- }
35
-
36
- function traverseArray(obj, path, index, typeStack) {
37
- if(!Array.isArray(obj)) return typeStack;
38
- const name = path[index];
39
- const element = obj[name];
40
- return traverseTyped(element, path, index+1, typeStack);
41
- }
42
-
43
- function traverseDict(obj, path, index, typeStack) {
44
- if(typeof obj !== 'object') return typeStack;
45
- const name = path[index];
46
- if(name === undefined) return typeStack;
47
- return traverseTyped(obj[name], path, index+1, typeStack);
48
- }
49
-
50
- function traverseDictArray(obj, path, index, typeStack) {
51
- if(typeof obj !== 'object') return typeStack;
52
- const name = path[index];
53
- if(name === undefined) return typeStack;
54
- return traverseArray(obj[name], path, index+1, typeStack);
55
- }
56
-
57
- function traverseTyped(obj, path, index, typeStack) {
58
- if(!obj) return typeStack;
59
- const name = path[index];
60
- if(name === undefined) return typeStack;
61
- if(name[0] === '@') return typeStack; // skip annotations
62
- const func = structuralNodeHandlers[name];
63
- if(func) return func(obj[name], path, index+1, typeStack.concat(name));
64
- // not typed -> columns?
65
- if(typeStack[typeStack.length-1] === 'columns')
66
- return traverseDictArray(obj, path, index, typeStack);
67
- return typeStack;
68
- }
69
-
70
- module.exports = {
71
- structuralPath
72
- }
@@ -1,171 +0,0 @@
1
- 'use strict';
2
-
3
- const { copyAnnotations } = require('../../model/csnUtils');
4
- const { cloneCsn, forEachDefinition } = require('../../model/csnUtils');
5
- const { attachPathOnPartialCSN } = require('./attachPath');
6
-
7
- // These functions are used for propagation of the annotations, virtual, key,
8
- // notNull attributes collected along the path during flattening.
9
- const { addPropsForPropagationFromElement, propagatePropsToElement, resetPropsForPropagation } = function () {
10
- let toBePropagated = Object.create(null);
11
- return {
12
- addPropsForPropagationFromElement: function (element) {
13
- copyAnnotations(element, toBePropagated);
14
- if (element.virtual) toBePropagated.virtual = element.virtual;
15
- if (element.key) toBePropagated.key = element.key;
16
- },
17
- propagatePropsToElement: function (element) {
18
- copyAnnotations(toBePropagated, element);
19
- if (toBePropagated.virtual) element.virtual = toBePropagated.virtual;
20
- if (toBePropagated.key) element.key = toBePropagated.key;
21
- },
22
- resetPropsForPropagation: function () {
23
- toBePropagated = Object.create(null);
24
- }
25
- }
26
- }();
27
-
28
- // keep here the state of the 'notNull' attribute
29
- // this is needed because during flattening all the elements
30
- // along the chain need to be assigned with not null so
31
- // the resulting element to be not null as well
32
- const { isNotNull, setNotNull, setUpNotNull } = function () {
33
- let notNull = undefined;
34
- return {
35
- isNotNull: function () {
36
- return notNull;
37
- },
38
- setNotNull: function (value) {
39
- notNull = value;
40
- },
41
- setUpNotNull: function (element, isParentNotNull) {
42
- if (isParentNotNull && element.notNull) setNotNull(element.notNull);
43
- else if (isNotNull() && !element.notNull || (isNotNull() === false && element.notNull !== false)) setNotNull(undefined);
44
- }
45
- }
46
- }();
47
-
48
- /**
49
- * During the OData transformations in flat-mode, all structured elements will be flattened.
50
- * This module performs the complete flattening.
51
- * It also provides information to the reference flattener: elements produced for specific path in the CSN structure.
52
- * @param {CSN.Model} csn CSN-object to flatten
53
- * @param {*} csnUtils instances of utility functions
54
- * @param {*} options
55
- * @param {*} referenceFlattener
56
- * @param {Function} error
57
- * @param {Function} isExternalServiceMember returns true for an artifact that is part of an external service
58
- */
59
- function flattenCSN(csn, csnUtils, options, referenceFlattener, error, isExternalServiceMember) {
60
- forEachDefinition(csn, (def, defName, propertyName, path) =>
61
- flattenDefinition(def, path, csnUtils, options, referenceFlattener, error), { skipArtifact: isExternalServiceMember });
62
- }
63
-
64
- /**
65
- * Flattens one single definition and all structures in it. Modifies the definition in place.
66
- * @param {CSN.Definition} definition definition object to flatten
67
- * @param {CSN.Path} definitionPath path in CSN object
68
- * @param {*} csnUtils utility functions
69
- * @param {*} options
70
- * @param {*} referenceFlattener
71
- * @param {Function} error
72
- */
73
- function flattenDefinition(definition, definitionPath, csnUtils, options, referenceFlattener, error) {
74
- if (definition.kind !== 'entity')
75
- return;
76
-
77
- let { newFlatElements } = flattenStructure(definition.elements, definitionPath, csnUtils, options, error, referenceFlattener);
78
-
79
- attachPathOnPartialCSN(newFlatElements, definitionPath.concat('elements'));
80
- definition.elements = newFlatElements;
81
-
82
- if (definition.params) {
83
- let { newFlatElements } = flattenStructure(definition.params, definitionPath, csnUtils, options, error, referenceFlattener);
84
- attachPathOnPartialCSN(newFlatElements, definitionPath.concat('params'));
85
- definition.params = newFlatElements;
86
- }
87
- } // flattenDefinition
88
-
89
- /**
90
- * Flattens structured element by calling element flattener for each structured child.
91
- * Returns a dictionary containing all the new elements for the given structure.
92
- * @param {*} dictionary to flatten
93
- * @param {CSN.Path} path the path of the structure in the CSN tree
94
- * @param {*} csnUtils
95
- * @param {Function} error Error message function
96
- * @param {*} [referenceFlattener]
97
- * @param {string[]} [elementPathInStructure] list of parent element names
98
- * @param {*} [newFlatElements]
99
- * @param {boolean} [isTopLevelElement] states if this is a top level element
100
- */
101
- function flattenStructure(dictionary, path, csnUtils, options, error, referenceFlattener = undefined, elementPathInStructure = [],
102
- newFlatElements = Object.create(null), isTopLevelElement = true, isParentNotNull = false) {
103
-
104
- if (!isTopLevelElement) addPropsForPropagationFromElement(dictionary);
105
-
106
- let generatedNewFlatElementsNames = []; // holds the names of all new child elements of the structure
107
-
108
- dictionary && Object.entries(dictionary).forEach(([elementName, element]) => {
109
- let currPath = path.concat('elements', elementName);
110
-
111
- if (isTopLevelElement) {
112
- resetPropsForPropagation();
113
- setNotNull(element.notNull)
114
- } else {
115
- setUpNotNull(element, isParentNotNull);
116
- }
117
-
118
- // flat elements when structured and NOT empty (allow incomplete structures - cds-compiler#4337)
119
- if (csnUtils.isStructured(element) && !(element.elements && Object.keys(element.elements).length === 0)) {
120
-
121
- if (referenceFlattener) referenceFlattener.registerFlattenedElement(currPath, element.$path);
122
-
123
- addPropsForPropagationFromElement(element);
124
-
125
- // if the child element is structured itself -> needs to be flattened
126
- const elements = element.elements || csnUtils.getFinalBaseType(element.type).elements;
127
- let result = flattenStructure(elements, currPath, csnUtils, options, error, referenceFlattener, elementPathInStructure.concat(elementName), newFlatElements, false, isNotNull());
128
- generatedNewFlatElementsNames.push(...result.generatedNewFlatElementsNames); // accomulate names of produced elements
129
-
130
- } else { // when we do not need to flat, this is scalar or empty (cds-compiler#4337) -> needs to be registered in referenceFlattener
131
- let newElementName = elementPathInStructure.concat(elementName).join('_');
132
- let elementNameWithDots = elementPathInStructure.concat(elementName).join('.');
133
- addNewElementToResult(element, newElementName, elementNameWithDots, currPath);
134
- }
135
- });
136
-
137
- if (referenceFlattener) {
138
- referenceFlattener.registerGeneratedElementsForPath(path, generatedNewFlatElementsNames);
139
- }
140
- return { newFlatElements, generatedNewFlatElementsNames };
141
-
142
- // adds newly created element into the final dictionary of elements
143
- function addNewElementToResult(element, elementName, elementNameWithDots, path) {
144
- if (newFlatElements[elementName]) {
145
- error(null, path, `Generated element ${elementName} conflicts with other generated element`);
146
- } else {
147
- let newPath = path.slice(0, 2).concat('elements', elementName);
148
- let newElement = createNewElement(element, elementNameWithDots, newPath);
149
- newFlatElements[elementName] = newElement;
150
- generatedNewFlatElementsNames.push(elementName);
151
-
152
- if (referenceFlattener) {
153
- referenceFlattener.registerElementTransition(path, newPath);
154
- }
155
- }
156
- } // addNewElementToResult
157
-
158
- // creates new element by copying the properties of the originating element
159
- function createNewElement(element, elementNameWithDots, path) {
160
- let newElement = cloneCsn(element, options);
161
- if (!isTopLevelElement) propagatePropsToElement(newElement);
162
- if (isNotNull() === undefined) delete newElement.notNull;
163
- if (!isTopLevelElement && referenceFlattener) {
164
- referenceFlattener.setElementNameWithDots(path, elementNameWithDots);
165
- }
166
- return newElement;
167
- } // createNewElement
168
-
169
- } // flattenStructure
170
-
171
- module.exports = { flattenCSN, flattenStructure };