@sap/cds-compiler 2.4.4 → 2.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +241 -1
- package/bin/.eslintrc.json +17 -0
- package/bin/cds_update_identifiers.js +8 -7
- package/bin/cdsc.js +180 -132
- package/bin/cdshi.js +18 -11
- package/bin/cdsse.js +38 -32
- package/bin/cdsv2m.js +8 -7
- package/doc/CHANGELOG_BETA.md +36 -1
- package/lib/api/main.js +81 -100
- package/lib/api/options.js +17 -11
- package/lib/api/validate.js +12 -8
- package/lib/backends.js +0 -81
- package/lib/base/keywords.js +32 -2
- package/lib/base/location.js +2 -2
- package/lib/base/message-registry.js +66 -4
- package/lib/base/messages.js +84 -27
- package/lib/base/model.js +2 -61
- package/lib/checks/arrayOfs.js +0 -1
- package/lib/checks/defaultValues.js +27 -2
- package/lib/checks/elements.js +1 -6
- package/lib/checks/enricher.js +8 -2
- 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 +27 -9
- package/lib/checks/selectItems.js +25 -2
- package/lib/checks/types.js +26 -2
- package/lib/checks/unknownMagic.js +38 -0
- package/lib/checks/utils.js +61 -0
- package/lib/checks/validator.js +66 -13
- package/lib/compiler/assert-consistency.js +24 -12
- package/lib/compiler/builtins.js +2 -0
- package/lib/compiler/checks.js +6 -4
- package/lib/compiler/definer.js +101 -39
- package/lib/compiler/index.js +88 -59
- package/lib/compiler/resolver.js +455 -209
- package/lib/compiler/shared.js +57 -33
- package/lib/edm/annotations/genericTranslation.js +183 -187
- package/lib/edm/csn2edm.js +128 -99
- package/lib/edm/edm.js +18 -21
- package/lib/edm/edmPreprocessor.js +361 -127
- package/lib/edm/edmUtils.js +103 -33
- package/lib/gen/Dictionary.json +74 -28
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +18 -4
- package/lib/gen/language.tokens +124 -118
- package/lib/gen/languageLexer.interp +13 -1
- package/lib/gen/languageLexer.js +870 -839
- package/lib/gen/languageLexer.tokens +116 -111
- package/lib/gen/languageParser.js +5894 -5614
- package/lib/json/from-csn.js +152 -67
- package/lib/json/to-csn.js +334 -135
- package/lib/language/antlrParser.js +4 -3
- package/lib/language/errorStrategy.js +1 -0
- package/lib/language/genericAntlrParser.js +24 -14
- package/lib/language/language.g4 +188 -128
- package/lib/main.d.ts +435 -0
- package/lib/main.js +31 -7
- package/lib/model/api.js +78 -0
- package/lib/model/csnRefs.js +463 -187
- package/lib/model/csnUtils.js +280 -136
- package/lib/model/enrichCsn.js +75 -4
- package/lib/model/revealInternalProperties.js +2 -1
- package/lib/modelCompare/compare.js +70 -25
- package/lib/optionProcessor.js +13 -10
- package/lib/render/.eslintrc.json +4 -1
- package/lib/render/DuplicateChecker.js +8 -5
- package/lib/render/toCdl.js +123 -40
- package/lib/render/toHdbcds.js +156 -65
- package/lib/render/toSql.js +87 -11
- package/lib/render/utils/common.js +55 -9
- package/lib/render/utils/sql.js +3 -3
- package/lib/sql-identifier.js +6 -1
- package/lib/transform/{sql → db}/.eslintrc.json +0 -0
- package/lib/transform/{sql → db}/assertUnique.js +7 -8
- package/lib/transform/{sql → db}/constraints.js +35 -20
- package/lib/transform/db/draft.js +353 -0
- package/lib/transform/db/expansion.js +582 -0
- package/lib/transform/db/flattening.js +325 -0
- package/lib/transform/{sql → db}/groupByOrderBy.js +8 -16
- package/lib/transform/{sql → db}/helpers.js +0 -0
- package/lib/transform/{sql → db}/transformExists.js +256 -60
- package/lib/transform/forHanaNew.js +216 -765
- package/lib/transform/forOdataNew.js +60 -56
- package/lib/transform/localized.js +48 -26
- package/lib/transform/odata/attachPath.js +19 -4
- package/lib/transform/odata/expandStructKeysInAssociations.js +2 -2
- package/lib/transform/odata/generateForeignKeyElements.js +13 -12
- package/lib/transform/odata/referenceFlattener.js +60 -36
- package/lib/transform/odata/sortByAssociationDependency.js +4 -4
- package/lib/transform/odata/structuralPath.js +76 -0
- package/lib/transform/odata/structureFlattener.js +21 -22
- package/lib/transform/odata/toFinalBaseType.js +5 -5
- package/lib/transform/odata/typesExposure.js +27 -17
- package/lib/transform/odata/utils.js +2 -2
- package/lib/transform/transformUtilsNew.js +141 -77
- package/lib/transform/translateAssocsToJoins.js +17 -14
- package/lib/transform/universalCsnEnricher.js +67 -0
- package/lib/utils/file.js +0 -11
- package/lib/utils/moduleResolve.js +6 -8
- package/lib/utils/timetrace.js +6 -1
- package/package.json +2 -1
- package/lib/base/deepCopy.js +0 -66
- package/lib/json/walker.js +0 -26
- package/lib/utils/string.js +0 -17
package/lib/main.d.ts
ADDED
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
// Official cds-compiler API.
|
|
2
|
+
// All functions and namespace documented here are available when
|
|
3
|
+
// @sap/cds-compiler is required.
|
|
4
|
+
//
|
|
5
|
+
// These types are improved step by step and use a lot any types at the moment.
|
|
6
|
+
|
|
7
|
+
export = compiler;
|
|
8
|
+
|
|
9
|
+
declare namespace compiler {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Options used by the core compiler and all backends.
|
|
13
|
+
*/
|
|
14
|
+
export type Options = {
|
|
15
|
+
[option: string]: any,
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Compiler and backend messages. Messages can be simple info messages but
|
|
19
|
+
* also warnings and errors. It is highly recommended to fix any warnings
|
|
20
|
+
* and to not ignore them.
|
|
21
|
+
* Errors stop the compilation process.
|
|
22
|
+
*/
|
|
23
|
+
messages?: object[]
|
|
24
|
+
/**
|
|
25
|
+
* Dictionary of message-ids and their reclassified severity. This option
|
|
26
|
+
* can be used to increase the severity of messages. The compiler will
|
|
27
|
+
* ignore decreased severities as this may lead to issues during
|
|
28
|
+
* compilation otherwise.
|
|
29
|
+
*/
|
|
30
|
+
severities?: { [messageId: string]: MessageSeverity}
|
|
31
|
+
/**
|
|
32
|
+
* Dictionary of beta flag names. This option allows fine-grained control
|
|
33
|
+
* over which beta features should be enabled.
|
|
34
|
+
* For a list of beta flag, please refer to `cdsc --help`.
|
|
35
|
+
*
|
|
36
|
+
* For backwards compatibility, this option may be `true` to indicate that
|
|
37
|
+
* all beta features should be enabled.
|
|
38
|
+
*/
|
|
39
|
+
beta?: { [betaFlag: string]: boolean } | boolean
|
|
40
|
+
/**
|
|
41
|
+
* If true, internal consistency checks are enabled and recompilation in
|
|
42
|
+
* backends is disabled.
|
|
43
|
+
*
|
|
44
|
+
* @internal This is an internal option and should not be used by end-users.
|
|
45
|
+
*/
|
|
46
|
+
testMode?: boolean
|
|
47
|
+
/**
|
|
48
|
+
* If true, CSN definitions are sorted by name. Implicitly enabled when testMode is true.
|
|
49
|
+
* `testMode` has higher priority, meaning if `testSortCsn` is `false` and `testMode` is true,
|
|
50
|
+
* definitions will still be sorted.
|
|
51
|
+
*/
|
|
52
|
+
testSortCsn?: boolean
|
|
53
|
+
/**
|
|
54
|
+
* A JS prototype that will be used for dictionaries created by the compiler.
|
|
55
|
+
* Dictionaries are e.g. "definitions" and "elements".
|
|
56
|
+
*/
|
|
57
|
+
dictionaryPrototype?: any
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The compiler's package version.
|
|
62
|
+
* For more details on versioning and SemVer, see `doc/Versioning.md`
|
|
63
|
+
*/
|
|
64
|
+
export function version(): string;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Main function: Compile the sources from the files given by the array of
|
|
68
|
+
* `filenames`. As usual with the `fs` library, relative file names are
|
|
69
|
+
* relative to the working directory `process.cwd()`. With argument `dir`, the
|
|
70
|
+
* file names are relative to `process.cwd()+dir`.
|
|
71
|
+
*
|
|
72
|
+
* This function returns a Promise and can be used with `await`. For an example
|
|
73
|
+
* see `examples/api-usage/`.
|
|
74
|
+
* See function {@link compileSync} or {@link compileSources} for alternative compile
|
|
75
|
+
* functions.
|
|
76
|
+
*
|
|
77
|
+
* The promise is fulfilled if all files could be read and processed without
|
|
78
|
+
* errors. The fulfillment value is a CSN model.
|
|
79
|
+
*
|
|
80
|
+
* If there are errors, the promise is rejected. If there was an invocation
|
|
81
|
+
* error (repeated filenames or if the file could not be read), the rejection
|
|
82
|
+
* value is an {@link InvocationError}. Otherwise, the rejection value is a
|
|
83
|
+
* {@link CompilationError} containing a vector of individual errors.
|
|
84
|
+
*
|
|
85
|
+
* @param filenames Array of files that should be compiled.
|
|
86
|
+
* @param options Compiler options. If you do not set `messages`, they will be printed to console.
|
|
87
|
+
* @param fileCache A dictionary of absolute file names to the file content with values:
|
|
88
|
+
* - false: the file does not exist
|
|
89
|
+
* - true: file exists (fstat), no further knowledge yet - i.e. value will change!
|
|
90
|
+
* - 'string' or Buffer: the file content
|
|
91
|
+
* - { realname: fs.realpath(filename) }: if filename is not canonicalized
|
|
92
|
+
*/
|
|
93
|
+
export function compile(filenames: string[], dir?: string, options?: Options, fileCache?: Record<string, any>): Promise<any>;
|
|
94
|
+
export function compileSync(filenames: string[], dir?: string, options?: Options, fileCache?: Record<string, any>): any;
|
|
95
|
+
export function compileSources(sourcesDict: any, options?: Options): any;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* In version 2 of cds-compiler, this is an identity function and
|
|
99
|
+
* is only kept for backwards compatibility.
|
|
100
|
+
*
|
|
101
|
+
* @deprecated
|
|
102
|
+
* @returns The input parameter "csn".
|
|
103
|
+
*/
|
|
104
|
+
export function compactModel(csn: CSN): any;
|
|
105
|
+
|
|
106
|
+
export class CompilationError extends Error {
|
|
107
|
+
constructor(messages: any, model: any, text: any, ...args);
|
|
108
|
+
messages: any[];
|
|
109
|
+
toString(): string;
|
|
110
|
+
/**
|
|
111
|
+
* If `options.attachValidNames` is set, this non-enumerable property holds the CSN model.
|
|
112
|
+
* @internal
|
|
113
|
+
*/
|
|
114
|
+
model?: CSN;
|
|
115
|
+
/**
|
|
116
|
+
* Used by `cdsc` to indicate whether the message was already printed to stderr.
|
|
117
|
+
* @private
|
|
118
|
+
*/
|
|
119
|
+
hasBeenReported: boolean;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Sort the given messages according to their location. Messages are sorted
|
|
124
|
+
* in ascending order according to their:
|
|
125
|
+
*
|
|
126
|
+
* - file name
|
|
127
|
+
* - start line
|
|
128
|
+
* - start column
|
|
129
|
+
* - end line
|
|
130
|
+
* - end column
|
|
131
|
+
* - semantic location (“home”)
|
|
132
|
+
* - message text
|
|
133
|
+
*
|
|
134
|
+
* If both messages do not have a location, they are sorted by their semantic
|
|
135
|
+
* location and then by their message text. If only one message has a file
|
|
136
|
+
* location, that message is sorted prior to those that don't have one.
|
|
137
|
+
*
|
|
138
|
+
* _Note_: Sorting is done in-place.
|
|
139
|
+
*
|
|
140
|
+
* Example of sorted messages:
|
|
141
|
+
* ```txt
|
|
142
|
+
* A.cds:1:11: Info id-3: First message text (in entity:“E”/element:“c”)
|
|
143
|
+
* A.cds:8:11: Error id-5: Another message text (in entity:“C”/element:“g”)
|
|
144
|
+
* B.cds:3:10: Debug id-7: First message text (in entity:“B”/element:“e”)
|
|
145
|
+
* B.cds:3:12: Warning id-4: Message text (in entity:“B”/element:“d”)
|
|
146
|
+
* B.cds:3:12: Error id-4: Message text (in entity:“B”/element:“e”)
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* If you also want to sort according to message's severity,
|
|
150
|
+
* see {@link sortMessagesSeverityAware}.
|
|
151
|
+
*
|
|
152
|
+
* @returns The same messages array as the input parameter.
|
|
153
|
+
*/
|
|
154
|
+
export function sortMessages(messages: CompileMessage[]): CompileMessage[];
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Sort the given messages in severity aware order. Messages are sorted first
|
|
158
|
+
* by severity where 'Error' comes first, then 'Warning' and so forth.
|
|
159
|
+
* Messages of the same severity are sorted the same as by {@link sortMessages}.
|
|
160
|
+
*
|
|
161
|
+
* _Note_: Sorting is done in-place.
|
|
162
|
+
*
|
|
163
|
+
* @returns The same messages array as the input parameter.
|
|
164
|
+
*/
|
|
165
|
+
export function sortMessagesSeverityAware(messages: CompileMessage[]): CompileMessage[];
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Removes duplicate messages from the given messages array without destroying
|
|
169
|
+
* references to the array, i.e. removes them in-place.
|
|
170
|
+
*
|
|
171
|
+
* _Note_: Does NOT keep the original order!
|
|
172
|
+
*
|
|
173
|
+
* Two messages are the same if they have the same message hash (see below).
|
|
174
|
+
* If one of the two is more precise, then it replaces the other.
|
|
175
|
+
* A message is more precise if it is contained in the other or if
|
|
176
|
+
* the first does not have an `endLine`/`endCol`.
|
|
177
|
+
*
|
|
178
|
+
* A “message hash” is the string representation of the message. If the
|
|
179
|
+
* message does not have a semantic location (“home”), the message hash
|
|
180
|
+
* is the result of {@link messageString}. If the message has a semantic
|
|
181
|
+
* location, the file location is stripped before being passed to
|
|
182
|
+
* {@link messageString}.
|
|
183
|
+
*/
|
|
184
|
+
export function deduplicateMessages(messages: CompileMessage[]): void;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Returns a message string with file- and semantic location if present in compact
|
|
188
|
+
* form (i.e. one line)
|
|
189
|
+
*
|
|
190
|
+
* Example:
|
|
191
|
+
* ```txt
|
|
192
|
+
* <source>.cds:3:11: Error message-id: Can't find type `nu` in this scope (in entity:“E”/element:“e”)
|
|
193
|
+
* ```
|
|
194
|
+
*
|
|
195
|
+
* @param normalizeFilename If true, the file path will be normalized to use `/` as the path separator.
|
|
196
|
+
* @param noMessageId If true, the message ID will _not_ be part of the string.
|
|
197
|
+
* @param noHome If true, the semantic location will _not_ be part of the string.
|
|
198
|
+
*/
|
|
199
|
+
export function messageString(msg: CompileMessage, normalizeFilename?: boolean, noMessageId?: boolean, noHome?: boolean): string;
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Returns a message string with file- and semantic location if present
|
|
203
|
+
* in multiline form.
|
|
204
|
+
* The error (+ message id) will be colored according to their severity if
|
|
205
|
+
* run on a TTY.
|
|
206
|
+
*
|
|
207
|
+
* Example:
|
|
208
|
+
* ```txt
|
|
209
|
+
* Error[message-id]: Can't find type `nu` in this scope (in entity:“E”/element:“e”)
|
|
210
|
+
* |
|
|
211
|
+
* <source>.cds:3:11, at entity:“E”
|
|
212
|
+
* ```
|
|
213
|
+
*
|
|
214
|
+
* @param config.normalizeFilename If true, the file path will be normalized to use `/` as the path separator.
|
|
215
|
+
* @param config.noMessageId If true, no messages id (in brackets) will be shown.
|
|
216
|
+
* @param config.hintExplanation If true, messages with explanations will get a "…" marker, see {@link hasMessageExplanation}.
|
|
217
|
+
* @param config.withLineSpacer If true, an additional line (with `|`) will be inserted between message and location.
|
|
218
|
+
*/
|
|
219
|
+
export function messageStringMultiline(msg: CompileMessage, config?: {
|
|
220
|
+
normalizeFilename?: boolean
|
|
221
|
+
noMessageId?: boolean
|
|
222
|
+
hintExplanation?: boolean
|
|
223
|
+
withLineSpacer?: boolean
|
|
224
|
+
}): string;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Returns a context (code) string for the given message that is human readable.
|
|
228
|
+
*
|
|
229
|
+
* The message context can be used to indicate to users where an error occurred.
|
|
230
|
+
* The line length is limited to 100 characters. If the message spans more than three
|
|
231
|
+
* lines, only the first three lines are printed and an ellipsis will be appended in the next line.
|
|
232
|
+
* If only one line is to be shown, the affected columns will be highlighted by a caret (`^`).
|
|
233
|
+
* All lines are prepended by a pipe (`|`) and show the corresponding line number.
|
|
234
|
+
*
|
|
235
|
+
* Example Output:
|
|
236
|
+
* ```txt
|
|
237
|
+
* |
|
|
238
|
+
* 13 | num * nu
|
|
239
|
+
* | ^^
|
|
240
|
+
* ```
|
|
241
|
+
*
|
|
242
|
+
* @param sourceLines The source code split up into lines, e.g. by `str.split(/\r\n?|\n/);`.
|
|
243
|
+
* @param msg Message whose location is used to print the message context.
|
|
244
|
+
*/
|
|
245
|
+
export function messageContext(sourceLines: string[], msg: CompileMessage): string;
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Get an explanatory text for a complicated compiler message with ID
|
|
249
|
+
* messageId. This function does a file lookup in `share/messages`.
|
|
250
|
+
* If the message explanation does not exist, an exception is thrown.
|
|
251
|
+
*
|
|
252
|
+
* @throws May throw an ENOENT error if the message explanation cannot be found.
|
|
253
|
+
* @see {@link hasMessageExplanation}
|
|
254
|
+
*/
|
|
255
|
+
export function explainMessage(messageId: string): string;
|
|
256
|
+
/**
|
|
257
|
+
* Returns `true` if the given messageId has an explanatory text.
|
|
258
|
+
* Contrary to {@link explainMessage}, this function does not make
|
|
259
|
+
* a file lookup.
|
|
260
|
+
*/
|
|
261
|
+
export function hasMessageExplanation(messageId: string): boolean;
|
|
262
|
+
|
|
263
|
+
export class InvocationError extends Error {
|
|
264
|
+
constructor(errs: any, ...args);
|
|
265
|
+
errors: any[]
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Returns true if at least one of the given messages is of severity "Error"
|
|
270
|
+
*/
|
|
271
|
+
export function hasErrors(messages: CompileMessage[]): boolean;
|
|
272
|
+
|
|
273
|
+
export function preparedCsnToEdm(csn: CSN, service: string, options: any): any;
|
|
274
|
+
export function preparedCsnToEdmx(csn: CSN, service: string, options: any): any;
|
|
275
|
+
|
|
276
|
+
export namespace parse {
|
|
277
|
+
/**
|
|
278
|
+
* Parse the given CDL in parseCdl mode and return its corresponding CSN representation.
|
|
279
|
+
*
|
|
280
|
+
* @param cdl CDL source as string.
|
|
281
|
+
* @param filename Filename to be used in compiler messages.
|
|
282
|
+
* @param options Compiler options. Note that if `options.messages` is not set, messages will be printed to stderr.
|
|
283
|
+
*/
|
|
284
|
+
function cdl(cdl: string, filename: string, options?: Options): any;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Parse the given CQL and return its corresponding CSN representation.
|
|
288
|
+
*
|
|
289
|
+
* @param cdl CDL source as string.
|
|
290
|
+
* @param filename Filename to be used in compiler messages, default is '<query>.cds'
|
|
291
|
+
* @param options Compiler options. Note that if `options.messages` is not set, messages will be printed to stderr.
|
|
292
|
+
*/
|
|
293
|
+
function cql(cdl: string, filename?: string, options?: Options): any;
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Parse the given CDL expression and return its corresponding CSN representation.
|
|
297
|
+
*
|
|
298
|
+
* @param cdl CDL source as string.
|
|
299
|
+
* @param filename Filename to be used in compiler messages, default is '<expr>.cds'
|
|
300
|
+
* @param options Compiler options. Note that if `options.messages` is not set, messages will be printed to stderr.
|
|
301
|
+
*/
|
|
302
|
+
function expr(cdl: string, filename?: string, options?: Options): any;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* @deprecated Use {@link parse.cql} instead.
|
|
307
|
+
*/
|
|
308
|
+
export function parseToCqn(cdl: string, filename?: string, options?: Options): any;
|
|
309
|
+
/**
|
|
310
|
+
* @deprecated Use {@link parse.expr} instead.
|
|
311
|
+
*/
|
|
312
|
+
export function parseToExpr(cdl: string, filename?: string, options?: Options): any;
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* @todo Actual name is "for" which isn't used in the doc as it is a reserved name.
|
|
316
|
+
* @alias for
|
|
317
|
+
*/
|
|
318
|
+
export namespace For {
|
|
319
|
+
function odata(): any;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export namespace to {
|
|
323
|
+
function cdl(csn: CSN, options: Options): object;
|
|
324
|
+
function sql(csn: CSN, options: Options): any;
|
|
325
|
+
|
|
326
|
+
function edm(csn: CSN, options: Options): any;
|
|
327
|
+
namespace edm {
|
|
328
|
+
function all(csn: CSN, options: Options): any;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function edmx(csn: CSN, options: Options): any;
|
|
332
|
+
namespace edmx {
|
|
333
|
+
function all(csn: CSN, options: Options): any;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function hdbcds(csn: CSN, options: Options): any;
|
|
337
|
+
function hdi(csn: CSN, options: Options): any;
|
|
338
|
+
namespace hdi {
|
|
339
|
+
function migration(csn: CSN, options: Options, beforeImage: any): any;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function getArtifactCdsPersistenceName(artifactName: string, namingConvention: any, csn: CSN): any;
|
|
344
|
+
export function getElementCdsPersistenceName(elemName: string, namingConvention: any): any;
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* @private
|
|
348
|
+
*/
|
|
349
|
+
export namespace $lsp {
|
|
350
|
+
function compile(filenames: string[], dir?: string, options?: Options, fileCache?: Record<string, any>): Promise<any>;
|
|
351
|
+
function parse(source: string, filename?: string, options?: Options): any;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* CSN object. Not yet specified in this TypeScript declaration file.
|
|
356
|
+
*/
|
|
357
|
+
export type CSN = any;
|
|
358
|
+
|
|
359
|
+
export class CompileMessage {
|
|
360
|
+
constructor(location: Location, msg: string, severity?: MessageSeverity, id?: string | null, home?: string | null, moduleName?: string | null);
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Optional ID of the message. Can be used to reclassify messages.
|
|
364
|
+
*
|
|
365
|
+
* @note This property is non-enumerable as message IDs are not finalized, yet.
|
|
366
|
+
*/
|
|
367
|
+
messageId?: string
|
|
368
|
+
|
|
369
|
+
severity: MessageSeverity
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* @deprecated Use `$location` instead.
|
|
373
|
+
*/
|
|
374
|
+
location: Location
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Location information like file and line/column of the message.
|
|
378
|
+
*/
|
|
379
|
+
$location: Location & {
|
|
380
|
+
address?: {
|
|
381
|
+
/**
|
|
382
|
+
* Fully qualified name of the affected definition.
|
|
383
|
+
*/
|
|
384
|
+
definition?: string
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* String representation of the message. May be a multi-line message in the future.
|
|
389
|
+
*/
|
|
390
|
+
message: string
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* A string describing the path to the artifact, e.g. `entity:"E"/element:"x"`.
|
|
394
|
+
*/
|
|
395
|
+
home?: string
|
|
396
|
+
/**
|
|
397
|
+
* Array of names that are valid at the specified position.
|
|
398
|
+
* Contains values if the message describes an "artifact not found" message.
|
|
399
|
+
*
|
|
400
|
+
* @internal Only to be used by the LSP implementation for CDS.
|
|
401
|
+
*/
|
|
402
|
+
validNames: string[] | null
|
|
403
|
+
/**
|
|
404
|
+
* If `internalMsg` is set, then this property will have an error object with a stack trace.
|
|
405
|
+
*/
|
|
406
|
+
error?: Error
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Returns a human readable string of the compiler message. Uses {@link messageString} to render
|
|
410
|
+
* the message without filename normalization and without a message ID.
|
|
411
|
+
*/
|
|
412
|
+
toString(): string;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Severities a compiler message can have.
|
|
417
|
+
*/
|
|
418
|
+
export type MessageSeverity = 'Error' | 'Warning' | 'Info' | 'Debug';
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* CSN Location, often exposed by `$location` in CSN.
|
|
422
|
+
* Columns and lines are 1-based, i.e. value `0` is an invalid value and
|
|
423
|
+
* indicates absence of the property.
|
|
424
|
+
*
|
|
425
|
+
* All properties are optional, even `file`.
|
|
426
|
+
*/
|
|
427
|
+
export type Location = {
|
|
428
|
+
file?: string
|
|
429
|
+
line?: number
|
|
430
|
+
col?: number
|
|
431
|
+
endLine?: number
|
|
432
|
+
endCol?: number
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
}
|
package/lib/main.js
CHANGED
|
@@ -16,10 +16,12 @@
|
|
|
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 { define } = require('./compiler/definer');
|
|
23
25
|
|
|
24
26
|
// The compiler version (taken from package.json)
|
|
25
27
|
function version() {
|
|
@@ -31,7 +33,6 @@ const {
|
|
|
31
33
|
messageString,
|
|
32
34
|
messageStringMultiline,
|
|
33
35
|
messageContext,
|
|
34
|
-
handleMessages,
|
|
35
36
|
hasErrors,
|
|
36
37
|
explainMessage,
|
|
37
38
|
hasMessageExplanation
|
|
@@ -39,19 +40,39 @@ const {
|
|
|
39
40
|
|
|
40
41
|
const { compactModel, compactQuery, compactExpr } = require('./json/to-csn')
|
|
41
42
|
|
|
43
|
+
function parseCdl( cdl, filename, options = {} ) {
|
|
44
|
+
options = Object.assign( {}, options, { parseCdl: true } );
|
|
45
|
+
const sources = Object.create(null);
|
|
46
|
+
const model = { sources, options };
|
|
47
|
+
const messageFunctions = createMessageFunctions( options, 'parse', model );
|
|
48
|
+
model.$messageFunctions = messageFunctions;
|
|
49
|
+
|
|
50
|
+
const xsn = parseLanguage( cdl, filename, Object.assign( { parseOnly: true }, options ),
|
|
51
|
+
messageFunctions );
|
|
52
|
+
sources[filename] = xsn;
|
|
53
|
+
define( model );
|
|
54
|
+
messageFunctions.throwWithError();
|
|
55
|
+
return compactModel( model );
|
|
56
|
+
}
|
|
57
|
+
|
|
42
58
|
function parseCql( cdl, filename = '<query>.cds', options = {} ) {
|
|
43
|
-
|
|
44
|
-
|
|
59
|
+
const messageFunctions = createMessageFunctions( options, 'parse' );
|
|
60
|
+
const xsn = parseLanguage( cdl, filename, Object.assign( { parseOnly: true }, options ),
|
|
61
|
+
messageFunctions, 'query' );
|
|
62
|
+
messageFunctions.throwWithError();
|
|
45
63
|
return compactQuery( xsn );
|
|
46
64
|
}
|
|
47
65
|
|
|
48
66
|
function parseExpr( cdl, filename = '<expr>.cds', options = {} ) {
|
|
49
|
-
|
|
50
|
-
|
|
67
|
+
const messageFunctions = createMessageFunctions( options, 'parse' );
|
|
68
|
+
const xsn = parseLanguage( cdl, filename, Object.assign( { parseOnly: true }, options ),
|
|
69
|
+
messageFunctions, 'expr' );
|
|
70
|
+
messageFunctions.throwWithError();
|
|
51
71
|
return compactExpr( xsn );
|
|
52
72
|
}
|
|
53
73
|
|
|
54
74
|
// FIXME: The implementation of those functions that delegate to 'backends' should probably move here
|
|
75
|
+
// ATTENTION: Keep in sync with main.d.ts!
|
|
55
76
|
module.exports = {
|
|
56
77
|
// Compiler
|
|
57
78
|
version,
|
|
@@ -78,7 +99,7 @@ module.exports = {
|
|
|
78
99
|
preparedCsnToEdm : (csn, service, options) => { return backends.preparedCsnToEdm(csn, service, options).edmj},
|
|
79
100
|
|
|
80
101
|
// additional API:
|
|
81
|
-
parse: { cql: parseCql, expr: parseExpr }, // preferred names
|
|
102
|
+
parse: { cdl: parseCdl, cql: parseCql, expr: parseExpr }, // preferred names
|
|
82
103
|
/**
|
|
83
104
|
* @deprecated Use parse.cql instead
|
|
84
105
|
*/
|
|
@@ -91,6 +112,9 @@ module.exports = {
|
|
|
91
112
|
getArtifactCdsPersistenceName: getArtifactDatabaseNameOf,
|
|
92
113
|
getElementCdsPersistenceName: getElementDatabaseNameOf,
|
|
93
114
|
|
|
115
|
+
// Other API functions:
|
|
116
|
+
traverseCsn,
|
|
117
|
+
|
|
94
118
|
// INTERNAL functions for the cds-lsp package and friends - before you use
|
|
95
119
|
// it, you MUST talk with us - there can be potential incompatibilities with
|
|
96
120
|
// 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
|
+
};
|