@sap/cds-compiler 2.5.2 → 2.11.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 +235 -9
- package/bin/cdsc.js +44 -27
- package/bin/cdsse.js +1 -0
- package/doc/CHANGELOG_BETA.md +37 -3
- package/lib/api/.eslintrc.json +2 -0
- package/lib/api/main.js +37 -123
- package/lib/api/options.js +27 -15
- package/lib/api/validate.js +34 -9
- package/lib/backends.js +9 -89
- package/lib/base/dictionaries.js +2 -1
- package/lib/base/keywords.js +32 -2
- package/lib/base/message-registry.js +73 -11
- package/lib/base/messages.js +86 -30
- package/lib/base/model.js +6 -6
- package/lib/base/optionProcessorHelper.js +56 -22
- package/lib/checks/defaultValues.js +27 -2
- package/lib/checks/elements.js +1 -6
- package/lib/checks/foreignKeys.js +0 -6
- package/lib/checks/managedWithoutKeys.js +17 -0
- package/lib/checks/nonexpandableStructured.js +38 -0
- package/lib/checks/onConditions.js +9 -45
- package/lib/checks/queryNoDbArtifacts.js +25 -7
- package/lib/checks/selectItems.js +29 -2
- package/lib/checks/types.js +26 -2
- package/lib/checks/unknownMagic.js +41 -0
- package/lib/checks/utils.js +61 -0
- package/lib/checks/validator.js +60 -7
- package/lib/compiler/assert-consistency.js +23 -7
- package/lib/compiler/base.js +65 -0
- package/lib/compiler/builtins.js +30 -1
- package/lib/compiler/checks.js +8 -5
- package/lib/compiler/definer.js +157 -133
- package/lib/compiler/index.js +89 -31
- package/lib/compiler/propagator.js +5 -2
- package/lib/compiler/resolver.js +375 -185
- package/lib/compiler/shared.js +49 -202
- package/lib/compiler/utils.js +173 -0
- package/lib/edm/annotations/genericTranslation.js +183 -187
- package/lib/edm/csn2edm.js +104 -108
- package/lib/edm/edm.js +18 -21
- package/lib/edm/edmPreprocessor.js +388 -146
- package/lib/edm/edmUtils.js +104 -34
- package/lib/gen/Dictionary.json +22 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +28 -1
- package/lib/gen/language.tokens +79 -69
- package/lib/gen/languageLexer.interp +28 -1
- package/lib/gen/languageLexer.js +879 -805
- package/lib/gen/languageLexer.tokens +71 -62
- package/lib/gen/languageParser.js +5330 -4300
- package/lib/json/from-csn.js +110 -52
- package/lib/json/to-csn.js +434 -120
- package/lib/language/antlrParser.js +15 -3
- package/lib/language/errorStrategy.js +1 -0
- package/lib/language/genericAntlrParser.js +93 -26
- package/lib/language/language.g4 +172 -31
- package/lib/main.d.ts +216 -19
- package/lib/main.js +32 -7
- package/lib/model/api.js +78 -0
- package/lib/model/csnRefs.js +413 -149
- package/lib/model/csnUtils.js +286 -75
- package/lib/model/enrichCsn.js +50 -6
- package/lib/model/revealInternalProperties.js +22 -5
- package/lib/modelCompare/compare.js +39 -21
- package/lib/optionProcessor.js +35 -18
- package/lib/render/.eslintrc.json +4 -1
- package/lib/render/DuplicateChecker.js +9 -6
- package/lib/render/toCdl.js +121 -36
- package/lib/render/toHdbcds.js +148 -98
- package/lib/render/toSql.js +114 -43
- package/lib/render/utils/common.js +8 -13
- package/lib/render/utils/sql.js +3 -3
- package/lib/sql-identifier.js +6 -1
- package/lib/transform/db/assertUnique.js +5 -6
- package/lib/transform/db/constraints.js +281 -106
- package/lib/transform/db/draft.js +11 -8
- package/lib/transform/db/expansion.js +584 -0
- package/lib/transform/db/flattening.js +341 -0
- package/lib/transform/db/groupByOrderBy.js +2 -2
- package/lib/transform/db/transformExists.js +345 -65
- package/lib/transform/db/views.js +438 -0
- package/lib/transform/forHanaNew.js +131 -793
- package/lib/transform/forOdataNew.js +30 -24
- package/lib/transform/localized.js +39 -10
- package/lib/transform/odata/attachPath.js +19 -4
- package/lib/transform/odata/generateForeignKeyElements.js +11 -10
- package/lib/transform/odata/referenceFlattener.js +60 -39
- package/lib/transform/odata/sortByAssociationDependency.js +2 -2
- package/lib/transform/odata/structuralPath.js +72 -0
- package/lib/transform/odata/structureFlattener.js +19 -18
- package/lib/transform/odata/typesExposure.js +22 -12
- package/lib/transform/transformUtilsNew.js +144 -78
- package/lib/transform/translateAssocsToJoins.js +22 -27
- package/lib/transform/universalCsnEnricher.js +67 -0
- package/lib/utils/file.js +5 -14
- package/lib/utils/moduleResolve.js +6 -8
- package/lib/utils/term.js +65 -42
- package/lib/utils/timetrace.js +48 -26
- package/package.json +1 -1
- package/lib/json/walker.js +0 -26
- package/lib/transform/sqlite +0 -0
- package/lib/utils/string.js +0 -17
package/lib/main.d.ts
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
//
|
|
5
5
|
// These types are improved step by step and use a lot any types at the moment.
|
|
6
6
|
|
|
7
|
+
// Author's note: All "options" interfaces should actually be types. However, due to
|
|
8
|
+
// https://github.com/TypeStrong/typedoc/issues/1519 we can't use
|
|
9
|
+
// intersection types at the moment.
|
|
10
|
+
|
|
7
11
|
export = compiler;
|
|
8
12
|
|
|
9
13
|
declare namespace compiler {
|
|
@@ -11,7 +15,7 @@ declare namespace compiler {
|
|
|
11
15
|
/**
|
|
12
16
|
* Options used by the core compiler and all backends.
|
|
13
17
|
*/
|
|
14
|
-
export
|
|
18
|
+
export interface Options {
|
|
15
19
|
[option: string]: any,
|
|
16
20
|
|
|
17
21
|
/**
|
|
@@ -57,6 +61,102 @@ declare namespace compiler {
|
|
|
57
61
|
dictionaryPrototype?: any
|
|
58
62
|
}
|
|
59
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Options used by OData backends. Includes options for the OData
|
|
66
|
+
* transformer as well as for rendering EDM and EDMX.
|
|
67
|
+
*/
|
|
68
|
+
export interface ODataOptions extends Options {
|
|
69
|
+
/**
|
|
70
|
+
* OData version for output files. Either 'v4' or 'v2'.
|
|
71
|
+
*
|
|
72
|
+
* @default 'v4'
|
|
73
|
+
*/
|
|
74
|
+
odataVersion?: string | 'v4' | 'v2'
|
|
75
|
+
/**
|
|
76
|
+
* Whether to generate OData as flat or as structured.
|
|
77
|
+
* Structured is only supported for OData v4.
|
|
78
|
+
*
|
|
79
|
+
* @default 'flat'
|
|
80
|
+
*/
|
|
81
|
+
odataFormat?: string | 'flat' | 'structured'
|
|
82
|
+
/**
|
|
83
|
+
* Naming mode used by the corresponding SQL.
|
|
84
|
+
*
|
|
85
|
+
* @default 'plain'
|
|
86
|
+
*/
|
|
87
|
+
sqlMapping?: string | 'plain' | 'quoted' | 'hdbcds'
|
|
88
|
+
/**
|
|
89
|
+
* If `true`, `cds.Compositions` are rendered as `edm:NavigationProperty` with the additional
|
|
90
|
+
* attribute `ContainsTarget="true"` and all contained entities (composition targets) have no
|
|
91
|
+
* `edm.EntitySet`.
|
|
92
|
+
*
|
|
93
|
+
* @note Only available for OData v4 EDM(X) rendering.
|
|
94
|
+
* @default false
|
|
95
|
+
*/
|
|
96
|
+
odataContainment?: boolean
|
|
97
|
+
/**
|
|
98
|
+
* If `true`, render generated foreign keys for managed associations.
|
|
99
|
+
* By default foreign keys are never visible in structured OData APIs.
|
|
100
|
+
*
|
|
101
|
+
* @note Only available for structured OData v4 EDM(X) rendering.
|
|
102
|
+
* @default false
|
|
103
|
+
*/
|
|
104
|
+
odataForeignKeys?: boolean
|
|
105
|
+
/**
|
|
106
|
+
* If `true`, association targets outside of the current service are added as
|
|
107
|
+
* `edm.EntityType` that only exposes their primary keys and have no `edm.EntitySet`.
|
|
108
|
+
* If the original association target is a service member, a corresponding `edm.Schema`
|
|
109
|
+
* representing the namespace of that service is added to `edm.Services`. All association
|
|
110
|
+
* targets that are no service members are collected in an `edm.Schema` with namespace `root`.
|
|
111
|
+
*
|
|
112
|
+
* @note Only valid for structured OData v4 EDM(X) rendering.
|
|
113
|
+
* @default false
|
|
114
|
+
* @since v2.1.0
|
|
115
|
+
*/
|
|
116
|
+
odataProxies?: boolean
|
|
117
|
+
/**
|
|
118
|
+
* This option is an extension to `odataProxies`.
|
|
119
|
+
* If `true`, an `edm:Reference` instead of a proxy `edm.EntityType` is rendered for each
|
|
120
|
+
* association target that is a service member outside the current service instead of proxies.
|
|
121
|
+
*
|
|
122
|
+
* @note Only valid for structured OData v4 EDM(X) rendering.
|
|
123
|
+
* @default false
|
|
124
|
+
* @since v2.1.0
|
|
125
|
+
*/
|
|
126
|
+
odataXServiceRefs?: boolean
|
|
127
|
+
/**
|
|
128
|
+
* The OData specification requires that all primary keys of the principal must be used as
|
|
129
|
+
* referential constraints. If an association is modelled with only a partial key, no
|
|
130
|
+
* referential constraints are added. If `true`, partial constraints are rendered for
|
|
131
|
+
* backwards compatibility and mocking scenarios. A spec violation warning is raised for
|
|
132
|
+
* each incomplete constraint.
|
|
133
|
+
*
|
|
134
|
+
* @note Only valid for OData v2 CSN transformation.
|
|
135
|
+
* @default false
|
|
136
|
+
* @since v2.2.6
|
|
137
|
+
*/
|
|
138
|
+
odataV2PartialConstr?: boolean
|
|
139
|
+
/**
|
|
140
|
+
* Service name for which EDMX or EDM shall be rendered.
|
|
141
|
+
*
|
|
142
|
+
* @note Only available for `to.edmx()` and `to.edm()`. For `to.edmx.all()`
|
|
143
|
+
* and `to.edm.all()`, use `serviceNames` instead.
|
|
144
|
+
*
|
|
145
|
+
* @see serviceNames
|
|
146
|
+
*/
|
|
147
|
+
service?: string
|
|
148
|
+
/**
|
|
149
|
+
* Array of service names for which EDMX or EDM shall be rendered.
|
|
150
|
+
* If unspecified, all services are rendered.
|
|
151
|
+
*
|
|
152
|
+
* @note Only available for `to.edmx.all()` and `to.edm.all()`. For `to.edmx()`
|
|
153
|
+
* and `to.edm()`, use `service` instead.
|
|
154
|
+
*
|
|
155
|
+
* @see service
|
|
156
|
+
*/
|
|
157
|
+
serviceNames?: string[]
|
|
158
|
+
}
|
|
159
|
+
|
|
60
160
|
/**
|
|
61
161
|
* The compiler's package version.
|
|
62
162
|
* For more details on versioning and SemVer, see `doc/Versioning.md`
|
|
@@ -83,6 +183,7 @@ declare namespace compiler {
|
|
|
83
183
|
* {@link CompilationError} containing a vector of individual errors.
|
|
84
184
|
*
|
|
85
185
|
* @param filenames Array of files that should be compiled.
|
|
186
|
+
* @param dir Working directory. Relative paths in `filenames` will be resolved relatively to this directory.
|
|
86
187
|
* @param options Compiler options. If you do not set `messages`, they will be printed to console.
|
|
87
188
|
* @param fileCache A dictionary of absolute file names to the file content with values:
|
|
88
189
|
* - false: the file does not exist
|
|
@@ -107,22 +208,92 @@ declare namespace compiler {
|
|
|
107
208
|
constructor(messages: any, model: any, text: any, ...args);
|
|
108
209
|
messages: any[];
|
|
109
210
|
toString(): string;
|
|
211
|
+
/**
|
|
212
|
+
* If `options.attachValidNames` is set, this non-enumerable property holds the CSN model.
|
|
213
|
+
* @internal
|
|
214
|
+
*/
|
|
215
|
+
model?: CSN;
|
|
216
|
+
/**
|
|
217
|
+
* Used by `cdsc` to indicate whether the message was already printed to stderr.
|
|
218
|
+
* @private
|
|
219
|
+
*/
|
|
220
|
+
hasBeenReported: boolean;
|
|
110
221
|
}
|
|
111
222
|
|
|
112
|
-
|
|
113
|
-
|
|
223
|
+
/**
|
|
224
|
+
* Sort the given messages according to their location. Messages are sorted
|
|
225
|
+
* in ascending order according to their:
|
|
226
|
+
*
|
|
227
|
+
* - file name
|
|
228
|
+
* - start line
|
|
229
|
+
* - start column
|
|
230
|
+
* - end line
|
|
231
|
+
* - end column
|
|
232
|
+
* - semantic location (“home”)
|
|
233
|
+
* - message text
|
|
234
|
+
*
|
|
235
|
+
* If both messages do not have a location, they are sorted by their semantic
|
|
236
|
+
* location and then by their message text. If only one message has a file
|
|
237
|
+
* location, that message is sorted prior to those that don't have one.
|
|
238
|
+
*
|
|
239
|
+
* _Note_: Sorting is done in-place.
|
|
240
|
+
*
|
|
241
|
+
* Example of sorted messages:
|
|
242
|
+
* ```
|
|
243
|
+
* A.cds:1:11: Info id-3: First message text (in entity:“E”/element:“c”)
|
|
244
|
+
* A.cds:8:11: Error id-5: Another message text (in entity:“C”/element:“g”)
|
|
245
|
+
* B.cds:3:10: Debug id-7: First message text (in entity:“B”/element:“e”)
|
|
246
|
+
* B.cds:3:12: Warning id-4: Message text (in entity:“B”/element:“d”)
|
|
247
|
+
* B.cds:3:12: Error id-4: Message text (in entity:“B”/element:“e”)
|
|
248
|
+
* ```
|
|
249
|
+
*
|
|
250
|
+
* If you also want to sort according to message's severity,
|
|
251
|
+
* see {@link sortMessagesSeverityAware}.
|
|
252
|
+
*
|
|
253
|
+
* @returns The same messages array as the input parameter.
|
|
254
|
+
*/
|
|
255
|
+
export function sortMessages(messages: CompileMessage[]): CompileMessage[];
|
|
114
256
|
|
|
115
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Sort the given messages in severity aware order. Messages are sorted first
|
|
259
|
+
* by severity where 'Error' comes first, then 'Warning' and so forth.
|
|
260
|
+
* Messages of the same severity are sorted the same as by {@link sortMessages}.
|
|
261
|
+
*
|
|
262
|
+
* _Note_: Sorting is done in-place.
|
|
263
|
+
*
|
|
264
|
+
* @returns The same messages array as the input parameter.
|
|
265
|
+
*/
|
|
266
|
+
export function sortMessagesSeverityAware(messages: CompileMessage[]): CompileMessage[];
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Removes duplicate messages from the given messages array without destroying
|
|
270
|
+
* references to the array, i.e. removes them in-place.
|
|
271
|
+
*
|
|
272
|
+
* _Note_: Does NOT keep the original order!
|
|
273
|
+
*
|
|
274
|
+
* Two messages are the same if they have the same message hash (see below).
|
|
275
|
+
* If one of the two is more precise, then it replaces the other.
|
|
276
|
+
* A message is more precise if it is contained in the other or if
|
|
277
|
+
* the first does not have an `endLine`/`endCol`.
|
|
278
|
+
*
|
|
279
|
+
* A “message hash” is the string representation of the message. If the
|
|
280
|
+
* message does not have a semantic location (“home”), the message hash
|
|
281
|
+
* is the result of {@link messageString}. If the message has a semantic
|
|
282
|
+
* location, the file location is stripped before being passed to
|
|
283
|
+
* {@link messageString}.
|
|
284
|
+
*/
|
|
285
|
+
export function deduplicateMessages(messages: CompileMessage[]): void;
|
|
116
286
|
|
|
117
287
|
/**
|
|
118
288
|
* Returns a message string with file- and semantic location if present in compact
|
|
119
289
|
* form (i.e. one line)
|
|
120
290
|
*
|
|
121
291
|
* Example:
|
|
122
|
-
* ```
|
|
292
|
+
* ```
|
|
123
293
|
* <source>.cds:3:11: Error message-id: Can't find type `nu` in this scope (in entity:“E”/element:“e”)
|
|
124
294
|
* ```
|
|
125
295
|
*
|
|
296
|
+
* @param msg Compiler message which shall be stringified.
|
|
126
297
|
* @param normalizeFilename If true, the file path will be normalized to use `/` as the path separator.
|
|
127
298
|
* @param noMessageId If true, the message ID will _not_ be part of the string.
|
|
128
299
|
* @param noHome If true, the semantic location will _not_ be part of the string.
|
|
@@ -132,26 +303,30 @@ declare namespace compiler {
|
|
|
132
303
|
/**
|
|
133
304
|
* Returns a message string with file- and semantic location if present
|
|
134
305
|
* in multiline form.
|
|
135
|
-
* The error (+ message id)
|
|
136
|
-
* run on a TTY.
|
|
306
|
+
* The error (+ message id) can colored according to their severity.
|
|
137
307
|
*
|
|
138
308
|
* Example:
|
|
139
|
-
* ```
|
|
140
|
-
* Error[message-id]: Can't find type `nu` in this scope
|
|
309
|
+
* ```
|
|
310
|
+
* Error[message-id]: Can't find type `nu` in this scope
|
|
141
311
|
* |
|
|
142
|
-
* <source>.cds:3:11, at entity:“E”
|
|
312
|
+
* <source>.cds:3:11, at entity:“E”/element:“e”
|
|
143
313
|
* ```
|
|
144
314
|
*
|
|
145
315
|
* @param config.normalizeFilename If true, the file path will be normalized to use `/` as the path separator.
|
|
146
316
|
* @param config.noMessageId If true, no messages id (in brackets) will be shown.
|
|
147
317
|
* @param config.hintExplanation If true, messages with explanations will get a "…" marker, see {@link hasMessageExplanation}.
|
|
148
318
|
* @param config.withLineSpacer If true, an additional line (with `|`) will be inserted between message and location.
|
|
319
|
+
* @param config.color If true, ANSI escape codes will be used for coloring the severity. If false, no
|
|
320
|
+
* coloring will be used. If 'auto', we will decide based on certain factors such
|
|
321
|
+
* as whether the shell is a TTY and whether the environment variable 'NO_COLOR' is
|
|
322
|
+
* unset.
|
|
149
323
|
*/
|
|
150
324
|
export function messageStringMultiline(msg: CompileMessage, config?: {
|
|
151
325
|
normalizeFilename?: boolean
|
|
152
326
|
noMessageId?: boolean
|
|
153
327
|
hintExplanation?: boolean
|
|
154
328
|
withLineSpacer?: boolean
|
|
329
|
+
color?: boolean | 'auto'
|
|
155
330
|
}): string;
|
|
156
331
|
|
|
157
332
|
/**
|
|
@@ -164,16 +339,24 @@ declare namespace compiler {
|
|
|
164
339
|
* All lines are prepended by a pipe (`|`) and show the corresponding line number.
|
|
165
340
|
*
|
|
166
341
|
* Example Output:
|
|
167
|
-
* ```
|
|
342
|
+
* ```
|
|
168
343
|
* |
|
|
169
344
|
* 13 | num * nu
|
|
170
345
|
* | ^^
|
|
171
346
|
* ```
|
|
172
347
|
*
|
|
173
|
-
* @param sourceLines
|
|
174
|
-
* @param msg
|
|
348
|
+
* @param sourceLines The source code split up into lines, e.g. by `str.split(/\r\n?|\n/);`.
|
|
349
|
+
* @param msg Message whose location is used to print the message context.
|
|
350
|
+
* @param config Configuration for the message context.
|
|
351
|
+
* @param config.color If true, ANSI escape codes will be used for coloring the severity. If false, no
|
|
352
|
+
* coloring will be used. If 'auto', we will decide based on certain factors such
|
|
353
|
+
* as whether the shell is a TTY and whether the environment variable 'NO_COLOR' is
|
|
354
|
+
* unset.
|
|
355
|
+
|
|
175
356
|
*/
|
|
176
|
-
export function messageContext(sourceLines: string[], msg: CompileMessage
|
|
357
|
+
export function messageContext(sourceLines: string[], msg: CompileMessage, config?: {
|
|
358
|
+
color?: boolean | 'auto'
|
|
359
|
+
}): string;
|
|
177
360
|
|
|
178
361
|
/**
|
|
179
362
|
* Get an explanatory text for a complicated compiler message with ID
|
|
@@ -205,6 +388,15 @@ declare namespace compiler {
|
|
|
205
388
|
export function preparedCsnToEdmx(csn: CSN, service: string, options: any): any;
|
|
206
389
|
|
|
207
390
|
export namespace parse {
|
|
391
|
+
/**
|
|
392
|
+
* Parse the given CDL in parseCdl mode and return its corresponding CSN representation.
|
|
393
|
+
*
|
|
394
|
+
* @param cdl CDL source as string.
|
|
395
|
+
* @param filename Filename to be used in compiler messages.
|
|
396
|
+
* @param options Compiler options. Note that if `options.messages` is not set, messages will be printed to stderr.
|
|
397
|
+
*/
|
|
398
|
+
function cdl(cdl: string, filename: string, options?: Options): any;
|
|
399
|
+
|
|
208
400
|
/**
|
|
209
401
|
* Parse the given CQL and return its corresponding CSN representation.
|
|
210
402
|
*
|
|
@@ -238,21 +430,26 @@ declare namespace compiler {
|
|
|
238
430
|
* @alias for
|
|
239
431
|
*/
|
|
240
432
|
export namespace For {
|
|
241
|
-
|
|
433
|
+
/**
|
|
434
|
+
* Transform the given (generic) CSN into one that is used for OData.
|
|
435
|
+
* Changes include flattening, type resolution and more, according to
|
|
436
|
+
* the provided options.
|
|
437
|
+
*/
|
|
438
|
+
function odata(csn: CSN, options: ODataOptions): any;
|
|
242
439
|
}
|
|
243
440
|
|
|
244
441
|
export namespace to {
|
|
245
442
|
function cdl(csn: CSN, options: Options): object;
|
|
246
443
|
function sql(csn: CSN, options: Options): any;
|
|
247
444
|
|
|
248
|
-
function edm(csn: CSN, options:
|
|
445
|
+
function edm(csn: CSN, options: ODataOptions): any;
|
|
249
446
|
namespace edm {
|
|
250
|
-
function all(csn: CSN, options:
|
|
447
|
+
function all(csn: CSN, options: ODataOptions): any;
|
|
251
448
|
}
|
|
252
449
|
|
|
253
|
-
function edmx(csn: CSN, options:
|
|
450
|
+
function edmx(csn: CSN, options: ODataOptions): any;
|
|
254
451
|
namespace edmx {
|
|
255
|
-
function all(csn: CSN, options:
|
|
452
|
+
function all(csn: CSN, options: ODataOptions): any;
|
|
256
453
|
}
|
|
257
454
|
|
|
258
455
|
function hdbcds(csn: CSN, options: Options): any;
|
package/lib/main.js
CHANGED
|
@@ -16,10 +16,13 @@
|
|
|
16
16
|
const backends = require('./backends');
|
|
17
17
|
const { odata, cdl, sql, hdi, hdbcds, edm, edmx } = require('./api/main');
|
|
18
18
|
const { getArtifactDatabaseNameOf, getElementDatabaseNameOf } = require('./model/csnUtils');
|
|
19
|
-
const {
|
|
19
|
+
const { traverseCsn } = require('./model/api');
|
|
20
|
+
const { createMessageFunctions, sortMessages, sortMessagesSeverityAware, deduplicateMessages } = require('./base/messages');
|
|
20
21
|
|
|
21
22
|
const parseLanguage = require('./language/antlrParser');
|
|
22
23
|
const { parseX, compileX, compileSyncX, compileSourcesX, InvocationError } = require('./compiler');
|
|
24
|
+
const { fns } = require('./compiler/shared');
|
|
25
|
+
const { define } = require('./compiler/definer');
|
|
23
26
|
|
|
24
27
|
// The compiler version (taken from package.json)
|
|
25
28
|
function version() {
|
|
@@ -31,7 +34,6 @@ const {
|
|
|
31
34
|
messageString,
|
|
32
35
|
messageStringMultiline,
|
|
33
36
|
messageContext,
|
|
34
|
-
handleMessages,
|
|
35
37
|
hasErrors,
|
|
36
38
|
explainMessage,
|
|
37
39
|
hasMessageExplanation
|
|
@@ -39,15 +41,35 @@ const {
|
|
|
39
41
|
|
|
40
42
|
const { compactModel, compactQuery, compactExpr } = require('./json/to-csn')
|
|
41
43
|
|
|
44
|
+
function parseCdl( cdl, filename, options = {} ) {
|
|
45
|
+
options = Object.assign( {}, options, { parseCdl: true } );
|
|
46
|
+
const sources = Object.create(null);
|
|
47
|
+
const model = { sources, options, $functions: {}, $volatileFunctions: {} };
|
|
48
|
+
const messageFunctions = createMessageFunctions( options, 'parse', model );
|
|
49
|
+
model.$messageFunctions = messageFunctions;
|
|
50
|
+
|
|
51
|
+
const xsn = parseLanguage( cdl, filename, Object.assign( { parseOnly: true }, options ),
|
|
52
|
+
messageFunctions );
|
|
53
|
+
sources[filename] = xsn;
|
|
54
|
+
fns( model );
|
|
55
|
+
define( model );
|
|
56
|
+
messageFunctions.throwWithError();
|
|
57
|
+
return compactModel( model );
|
|
58
|
+
}
|
|
59
|
+
|
|
42
60
|
function parseCql( cdl, filename = '<query>.cds', options = {} ) {
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
const messageFunctions = createMessageFunctions( options, 'parse' );
|
|
62
|
+
const xsn = parseLanguage( cdl, filename, Object.assign( { parseOnly: true }, options ),
|
|
63
|
+
messageFunctions, 'query' );
|
|
64
|
+
messageFunctions.throwWithError();
|
|
45
65
|
return compactQuery( xsn );
|
|
46
66
|
}
|
|
47
67
|
|
|
48
68
|
function parseExpr( cdl, filename = '<expr>.cds', options = {} ) {
|
|
49
|
-
|
|
50
|
-
|
|
69
|
+
const messageFunctions = createMessageFunctions( options, 'parse' );
|
|
70
|
+
const xsn = parseLanguage( cdl, filename, Object.assign( { parseOnly: true }, options ),
|
|
71
|
+
messageFunctions, 'expr' );
|
|
72
|
+
messageFunctions.throwWithError();
|
|
51
73
|
return compactExpr( xsn );
|
|
52
74
|
}
|
|
53
75
|
|
|
@@ -79,7 +101,7 @@ module.exports = {
|
|
|
79
101
|
preparedCsnToEdm : (csn, service, options) => { return backends.preparedCsnToEdm(csn, service, options).edmj},
|
|
80
102
|
|
|
81
103
|
// additional API:
|
|
82
|
-
parse: { cql: parseCql, expr: parseExpr }, // preferred names
|
|
104
|
+
parse: { cdl: parseCdl, cql: parseCql, expr: parseExpr }, // preferred names
|
|
83
105
|
/**
|
|
84
106
|
* @deprecated Use parse.cql instead
|
|
85
107
|
*/
|
|
@@ -92,6 +114,9 @@ module.exports = {
|
|
|
92
114
|
getArtifactCdsPersistenceName: getArtifactDatabaseNameOf,
|
|
93
115
|
getElementCdsPersistenceName: getElementDatabaseNameOf,
|
|
94
116
|
|
|
117
|
+
// Other API functions:
|
|
118
|
+
traverseCsn,
|
|
119
|
+
|
|
95
120
|
// INTERNAL functions for the cds-lsp package and friends - before you use
|
|
96
121
|
// it, you MUST talk with us - there can be potential incompatibilities with
|
|
97
122
|
// new releases (even having the same major version):
|
package/lib/model/api.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Miscellaneous CSN functions we put into our compiler API
|
|
2
|
+
|
|
3
|
+
// Do not change at will - they are in the compiler API!
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Dictionary of default traversal functions for function `traverseCsn`.
|
|
7
|
+
* It maps CSN property names to functions which are used by default
|
|
8
|
+
* to traverse the CSN node which is the value of the corresponding property.
|
|
9
|
+
* Users specify their own traversal function via argument `userFunctions`.
|
|
10
|
+
*
|
|
11
|
+
* Each function in `userFunctions` and `defaultFunctions` is called with:
|
|
12
|
+
* - `userFunctions`
|
|
13
|
+
* - the current CSN node, i.e. ‹parent node›.‹property name›
|
|
14
|
+
* - the the ‹parent node›
|
|
15
|
+
* - the ‹property name› (might be useful if the same function is used for several props)
|
|
16
|
+
*/
|
|
17
|
+
const defaultFunctions = {
|
|
18
|
+
'@': () => { /* do not traverse annotation assignments */ },
|
|
19
|
+
args: dictionary,
|
|
20
|
+
elements: dictionary,
|
|
21
|
+
enum: dictionary,
|
|
22
|
+
params: dictionary,
|
|
23
|
+
actions: dictionary,
|
|
24
|
+
mixin: dictionary,
|
|
25
|
+
definitions: dictionary,
|
|
26
|
+
'$': () => { /* do not traverse properties starting with '$' */},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Traverse the CSN node `csn`.
|
|
31
|
+
* If `csn` is an array, call it recursively on each array item.
|
|
32
|
+
* If `csn` is an(other) object, call a function on each property:
|
|
33
|
+
* - The property name is a used as key in argument `userFunctions` and the
|
|
34
|
+
* constant `defaultFunctions` above to get the function which is called on
|
|
35
|
+
* the property value, see `defaultFunctions` for details.
|
|
36
|
+
* - If no function is found with the property name, try to find one with the first char.
|
|
37
|
+
* - If still not found, call `traverseCsn` recursively.
|
|
38
|
+
*
|
|
39
|
+
* The functions in `userFunctions` are usually transformer functions, which
|
|
40
|
+
* change the input CSN destructively.
|
|
41
|
+
*/
|
|
42
|
+
function traverseCsn( userFunctions, csn ) {
|
|
43
|
+
if (!csn || typeof csn !== 'object')
|
|
44
|
+
return;
|
|
45
|
+
if (Array.isArray( csn )) {
|
|
46
|
+
csn.forEach( node => traverseCsn( userFunctions, node ) );
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
for (const prop of Object.keys( csn )) {
|
|
50
|
+
const func = userFunctions[prop] || defaultFunctions[prop] ||
|
|
51
|
+
userFunctions[prop.charAt(0)] || defaultFunctions[prop.charAt(0)] ||
|
|
52
|
+
traverseCsn;
|
|
53
|
+
func( userFunctions, csn[prop], csn, prop );
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// people might want to have their own traversal function for `elements`, etc:
|
|
58
|
+
traverseCsn.dictionary = dictionary;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Traverse the CSN dictionary node `csn`.
|
|
62
|
+
* Call `traverseCsn` on each property value in `csn`, passing down `userFunctions`.
|
|
63
|
+
*/
|
|
64
|
+
function dictionary( userFunctions, csn ) {
|
|
65
|
+
if (!csn || typeof csn !== 'object')
|
|
66
|
+
return;
|
|
67
|
+
if (Array.isArray( csn )) { // args can be both array and dictionary
|
|
68
|
+
csn.forEach( node => traverseCsn( userFunctions, node ) );
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
for (const name of Object.keys( csn ))
|
|
72
|
+
traverseCsn( userFunctions, csn[name] );
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = {
|
|
77
|
+
traverseCsn,
|
|
78
|
+
};
|