@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/bin/cdsc.js
CHANGED
|
@@ -17,15 +17,16 @@
|
|
|
17
17
|
|
|
18
18
|
const compiler = require('../lib/compiler');
|
|
19
19
|
const main = require('../lib/main');
|
|
20
|
+
const { for_sql, for_hdi, for_hdbcds } = require('../lib/api/main');
|
|
20
21
|
const { compactModel } = require('../lib/json/to-csn');
|
|
21
|
-
const {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
const { toRenameWithCsn, alterConstraintsWithCsn } = require('../lib/backends');
|
|
23
|
+
const util = require('util');
|
|
24
|
+
const fs = require('fs');
|
|
25
|
+
const path = require('path');
|
|
26
|
+
const { reveal } = require('../lib/model/revealInternalProperties');
|
|
26
27
|
const enrichCsn = require('../lib/model/enrichCsn');
|
|
27
28
|
const { optionProcessor } = require('../lib/optionProcessor');
|
|
28
|
-
const { explainMessage, hasMessageExplanation, sortMessages } = require('../lib/base/messages')
|
|
29
|
+
const { explainMessage, hasMessageExplanation, sortMessages } = require('../lib/base/messages');
|
|
29
30
|
const term = require('../lib/utils/term');
|
|
30
31
|
const { splitLines } = require('../lib/utils/file');
|
|
31
32
|
const { addLocalizationViews } = require('../lib/transform/localized');
|
|
@@ -35,27 +36,59 @@ const { availableBetaFlags } = require('../lib/base/model');
|
|
|
35
36
|
// but that might truncate the output of stdout and stderr, both of which are async (or rather,
|
|
36
37
|
// may possibly be async, depending on OS and whether I/O goes to TTY, socket, file, ... sigh)
|
|
37
38
|
class ProcessExitError extends Error {
|
|
38
|
-
constructor(exitCode
|
|
39
|
+
constructor(exitCode, ...args) {
|
|
39
40
|
super(...args);
|
|
40
41
|
this.exitCode = exitCode;
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
function remapCmdOptions(options, cmdOptions) {
|
|
46
|
+
if (!cmdOptions)
|
|
47
|
+
return options;
|
|
48
|
+
|
|
49
|
+
for (const [ key, value ] of Object.entries(cmdOptions)) {
|
|
50
|
+
switch (key) {
|
|
51
|
+
case 'names':
|
|
52
|
+
options.sqlMapping = value;
|
|
53
|
+
break;
|
|
54
|
+
case 'user':
|
|
55
|
+
if (!options.magicVars)
|
|
56
|
+
options.magicVars = {};
|
|
57
|
+
options.magicVars.user = value;
|
|
58
|
+
break;
|
|
59
|
+
case 'dialect':
|
|
60
|
+
options.sqlDialect = value;
|
|
61
|
+
break;
|
|
62
|
+
case 'version':
|
|
63
|
+
options.odataVersion = value;
|
|
64
|
+
break;
|
|
65
|
+
case 'locale':
|
|
66
|
+
if (!options.magicVars)
|
|
67
|
+
options.magicVars = {};
|
|
68
|
+
options.magicVars.locale = value;
|
|
69
|
+
break;
|
|
70
|
+
default:
|
|
71
|
+
options[key] = value;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return options;
|
|
75
|
+
}
|
|
76
|
+
|
|
44
77
|
// Parse the command line and translate it into options
|
|
45
78
|
try {
|
|
46
|
-
|
|
79
|
+
const cmdLine = optionProcessor.processCmdLine(process.argv);
|
|
47
80
|
// Deal with '--version' explicitly
|
|
48
81
|
if (cmdLine.options.version) {
|
|
49
|
-
process.stdout.write(main.version()
|
|
82
|
+
process.stdout.write(`${main.version()}\n`);
|
|
50
83
|
throw new ProcessExitError(0);
|
|
51
84
|
}
|
|
52
85
|
// Deal with '--help' explicitly
|
|
53
86
|
if (cmdLine.command) {
|
|
54
87
|
// Command specific help
|
|
55
|
-
if (cmdLine.options.help || cmdLine.options[cmdLine.command] && cmdLine.options[cmdLine.command].help)
|
|
88
|
+
if (cmdLine.options.help || cmdLine.options[cmdLine.command] && cmdLine.options[cmdLine.command].help)
|
|
56
89
|
displayUsage(null, optionProcessor.commands[cmdLine.command].helpText, 0);
|
|
57
|
-
|
|
58
|
-
|
|
90
|
+
}
|
|
91
|
+
else if (cmdLine.options.help) {
|
|
59
92
|
// General help
|
|
60
93
|
displayUsage(null, optionProcessor.helpText, 0);
|
|
61
94
|
}
|
|
@@ -70,20 +103,21 @@ try {
|
|
|
70
103
|
if (cmdLine.cmdErrors.length > 0) {
|
|
71
104
|
// Command specific errors
|
|
72
105
|
displayUsage(cmdLine.cmdErrors, optionProcessor.commands[cmdLine.command].helpText, 2);
|
|
73
|
-
}
|
|
106
|
+
}
|
|
107
|
+
else if (cmdLine.errors.length > 0) {
|
|
74
108
|
// General errors
|
|
75
109
|
displayUsage(cmdLine.errors, optionProcessor.helpText, 2);
|
|
76
110
|
}
|
|
77
111
|
|
|
78
112
|
// Default warning level is 2 (info)
|
|
79
113
|
// FIXME: Is that not set anywhere in the API?
|
|
80
|
-
if (!cmdLine.options.warning)
|
|
114
|
+
if (!cmdLine.options.warning)
|
|
81
115
|
cmdLine.options.warning = 2;
|
|
82
|
-
|
|
116
|
+
|
|
83
117
|
// Default output goes to stdout
|
|
84
|
-
if (!cmdLine.options.out)
|
|
118
|
+
if (!cmdLine.options.out)
|
|
85
119
|
cmdLine.options.out = '-';
|
|
86
|
-
|
|
120
|
+
|
|
87
121
|
// --cds-home <dir>: modules starting with '@sap/cds/' are searched in <dir>
|
|
88
122
|
if (cmdLine.options.cdsHome) {
|
|
89
123
|
if (!global.cds)
|
|
@@ -105,39 +139,43 @@ try {
|
|
|
105
139
|
cmdLine.options.parseCdl = true;
|
|
106
140
|
if (cmdLine.args.files.length > 1) {
|
|
107
141
|
const err = `'parseCdl' expects exactly one file! ${cmdLine.args.files.length} provided.`;
|
|
108
|
-
displayUsage(err, optionProcessor.commands
|
|
142
|
+
displayUsage(err, optionProcessor.commands.parseCdl.helpText, 2);
|
|
109
143
|
}
|
|
110
144
|
}
|
|
111
145
|
|
|
112
|
-
if (cmdLine.options.directBackend)
|
|
146
|
+
if (cmdLine.options.directBackend)
|
|
113
147
|
validateDirectBackendOption(cmdLine.command, cmdLine.options, cmdLine.args);
|
|
114
|
-
|
|
148
|
+
|
|
115
149
|
|
|
116
150
|
if (cmdLine.options.beta) {
|
|
117
151
|
const features = cmdLine.options.beta.split(',');
|
|
118
152
|
cmdLine.options.beta = {};
|
|
119
|
-
features.forEach((val) =>
|
|
153
|
+
features.forEach((val) => {
|
|
154
|
+
cmdLine.options.beta[val] = true;
|
|
155
|
+
});
|
|
120
156
|
}
|
|
121
157
|
|
|
122
158
|
// Enable all beta-flags if betaMode is set to true
|
|
123
|
-
if(cmdLine.options.betaMode)
|
|
159
|
+
if (cmdLine.options.betaMode)
|
|
124
160
|
cmdLine.options.beta = availableBetaFlags;
|
|
125
|
-
|
|
161
|
+
|
|
126
162
|
if (cmdLine.options.deprecated) {
|
|
127
163
|
const features = cmdLine.options.deprecated.split(',');
|
|
128
164
|
cmdLine.options.deprecated = {};
|
|
129
|
-
features.forEach((val) =>
|
|
165
|
+
features.forEach((val) => {
|
|
166
|
+
cmdLine.options.deprecated[val] = true;
|
|
167
|
+
});
|
|
130
168
|
}
|
|
131
169
|
// Do the work for the selected command
|
|
132
170
|
executeCommandLine(cmdLine.command, cmdLine.options, cmdLine.args);
|
|
133
|
-
}
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
134
173
|
// This whole try/catch is only here because process.exit does not work in combination with
|
|
135
174
|
// stdout/err - see comment at ProcessExitError
|
|
136
|
-
if (err instanceof ProcessExitError)
|
|
175
|
+
if (err instanceof ProcessExitError)
|
|
137
176
|
process.exitCode = err.exitCode;
|
|
138
|
-
|
|
177
|
+
else
|
|
139
178
|
throw err;
|
|
140
|
-
}
|
|
141
179
|
}
|
|
142
180
|
|
|
143
181
|
/**
|
|
@@ -150,33 +188,32 @@ try {
|
|
|
150
188
|
* @param {object} args
|
|
151
189
|
*/
|
|
152
190
|
function validateDirectBackendOption(command, options, args) {
|
|
153
|
-
if (!['toCdl', 'toOdata', 'toHana', 'toCsn', 'toSql'].includes(command)) {
|
|
191
|
+
if (![ 'toCdl', 'toOdata', 'toHana', 'toCsn', 'toSql' ].includes(command)) {
|
|
154
192
|
displayUsage(`Option '--direct-backend' can't be used with command '${command}'`,
|
|
155
|
-
|
|
193
|
+
optionProcessor.helpText, 2);
|
|
156
194
|
}
|
|
157
195
|
if (!args.files || args.files.length !== 1) {
|
|
158
196
|
displayUsage(`Option '--direct-backend' expects exactly one JSON file, but ${args.files.length} given`,
|
|
159
|
-
|
|
197
|
+
optionProcessor.helpText, 2);
|
|
160
198
|
}
|
|
161
199
|
const filename = args.files[0];
|
|
162
200
|
if (!filename.endsWith('.csn') && !filename.endsWith('.json')) {
|
|
163
|
-
displayUsage(
|
|
164
|
-
|
|
201
|
+
displayUsage('Option \'--direct-backend\' expects a filename with a *.csn or *.json suffix',
|
|
202
|
+
optionProcessor.helpText, 2);
|
|
165
203
|
}
|
|
166
204
|
}
|
|
167
205
|
|
|
168
206
|
// Display help text 'helpText' and 'error' (if any), then exit with exit code <code>
|
|
169
207
|
function displayUsage(error, helpText, code) {
|
|
170
208
|
// Display non-error output (like help) to stdout
|
|
171
|
-
|
|
209
|
+
const out = (code === 0 && !error) ? process.stdout : process.stderr;
|
|
172
210
|
// Display help text first, error at the end (more readable, no scrolling)
|
|
173
211
|
out.write(`${helpText}\n`);
|
|
174
212
|
if (error) {
|
|
175
|
-
if (error instanceof Array)
|
|
176
|
-
out.write(error.map(error => `cdsc: ERROR: ${error}`).join('\n')
|
|
177
|
-
|
|
213
|
+
if (error instanceof Array)
|
|
214
|
+
out.write(`${error.map(error => `cdsc: ERROR: ${error}`).join('\n')}\n`);
|
|
215
|
+
else
|
|
178
216
|
out.write(`cdsc: ERROR: ${error}\n`);
|
|
179
|
-
}
|
|
180
217
|
}
|
|
181
218
|
throw new ProcessExitError(code);
|
|
182
219
|
}
|
|
@@ -184,14 +221,16 @@ function displayUsage(error, helpText, code) {
|
|
|
184
221
|
// Executes a command line that has been translated to 'command' (what to do), 'options' (how) and 'args' (which files)
|
|
185
222
|
function executeCommandLine(command, options, args) {
|
|
186
223
|
const normalizeFilename = options.testMode && process.platform === 'win32';
|
|
187
|
-
const messageLevels = {
|
|
224
|
+
const messageLevels = {
|
|
225
|
+
Error: 0, Warning: 1, Info: 2, None: 3,
|
|
226
|
+
};
|
|
188
227
|
// All messages are put into the message array, even those which should not
|
|
189
228
|
// been displayed (severity 'None')
|
|
190
229
|
|
|
191
230
|
// Create output directory if necessary
|
|
192
|
-
if (options.out && options.out !== '-' && !fs.existsSync(options.out))
|
|
231
|
+
if (options.out && options.out !== '-' && !fs.existsSync(options.out))
|
|
193
232
|
fs.mkdirSync(options.out);
|
|
194
|
-
|
|
233
|
+
|
|
195
234
|
|
|
196
235
|
// Add implementation functions corresponding to commands here
|
|
197
236
|
const commands = {
|
|
@@ -207,9 +246,9 @@ function executeCommandLine(command, options, args) {
|
|
|
207
246
|
explain,
|
|
208
247
|
};
|
|
209
248
|
|
|
210
|
-
if (!commands[command] && !commandsWithoutCompilation[command])
|
|
249
|
+
if (!commands[command] && !commandsWithoutCompilation[command])
|
|
211
250
|
throw new Error(`Missing implementation for command ${command}`);
|
|
212
|
-
|
|
251
|
+
|
|
213
252
|
|
|
214
253
|
if (commandsWithoutCompilation[command]) {
|
|
215
254
|
commandsWithoutCompilation[command]();
|
|
@@ -218,14 +257,14 @@ function executeCommandLine(command, options, args) {
|
|
|
218
257
|
|
|
219
258
|
options.messages = [];
|
|
220
259
|
|
|
221
|
-
const fileCache = Object.create(null)
|
|
222
|
-
const compiled = options.directBackend
|
|
223
|
-
util.promisify(fs.readFile)( args.files[0], 'utf-8' ).then(
|
|
224
|
-
compiler.compileX( args.files, undefined, options, fileCache );
|
|
260
|
+
const fileCache = Object.create(null);
|
|
261
|
+
const compiled = options.directBackend
|
|
262
|
+
? util.promisify(fs.readFile)( args.files[0], 'utf-8' ).then(str => JSON.parse( str ))
|
|
263
|
+
: compiler.compileX( args.files, undefined, options, fileCache );
|
|
225
264
|
|
|
226
265
|
compiled.then( commands[command] )
|
|
227
|
-
|
|
228
|
-
|
|
266
|
+
.then( displayMessages, displayErrors )
|
|
267
|
+
.catch( catchErrors );
|
|
229
268
|
|
|
230
269
|
return; // below are only command implementations.
|
|
231
270
|
|
|
@@ -233,10 +272,10 @@ function executeCommandLine(command, options, args) {
|
|
|
233
272
|
// Return the original model (for chaining)
|
|
234
273
|
function toCdl( model ) {
|
|
235
274
|
const csn = options.directBackend ? model : compactModel(model, options);
|
|
236
|
-
const cdlResult =
|
|
237
|
-
for (const name in cdlResult)
|
|
238
|
-
writeToFileOrDisplay(options.out, name
|
|
239
|
-
|
|
275
|
+
const cdlResult = main.to.cdl(csn, remapCmdOptions(options));
|
|
276
|
+
for (const name in cdlResult)
|
|
277
|
+
writeToFileOrDisplay(options.out, `${name}.cds`, cdlResult[name]);
|
|
278
|
+
|
|
240
279
|
return model;
|
|
241
280
|
}
|
|
242
281
|
|
|
@@ -245,7 +284,8 @@ function executeCommandLine(command, options, args) {
|
|
|
245
284
|
function toCsn( model ) {
|
|
246
285
|
if (options.directBackend) {
|
|
247
286
|
displayNamedCsn(model, 'csn', options);
|
|
248
|
-
}
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
249
289
|
// Result already provided by caller
|
|
250
290
|
displayNamedXsn(model, 'csn', options);
|
|
251
291
|
}
|
|
@@ -256,99 +296,105 @@ function executeCommandLine(command, options, args) {
|
|
|
256
296
|
// Return the original model (for chaining)
|
|
257
297
|
function toHana( model ) {
|
|
258
298
|
const csn = options.directBackend ? model : compactModel(model, options);
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
writeToFileOrDisplay(options.out, `${name}.${pluginName}`, hanaResult[pluginName][name]);
|
|
263
|
-
}
|
|
299
|
+
|
|
300
|
+
if (options.toHana && options.toHana.csn) {
|
|
301
|
+
displayNamedCsn(for_hdbcds(csn, remapCmdOptions(options, options.toHana)), 'hana_csn', options);
|
|
264
302
|
}
|
|
265
|
-
|
|
303
|
+
else {
|
|
304
|
+
const hanaResult = main.to.hdbcds(csn, remapCmdOptions(options, options.toHana));
|
|
305
|
+
for (const name in hanaResult)
|
|
306
|
+
writeToFileOrDisplay(options.out, name, hanaResult[name]);
|
|
307
|
+
}
|
|
308
|
+
|
|
266
309
|
return model;
|
|
267
310
|
}
|
|
268
311
|
|
|
269
312
|
// Execute the command line option '--to-odata' and display the results.
|
|
270
313
|
// Return the original model (for chaining)
|
|
271
314
|
function toOdata( model ) {
|
|
272
|
-
if(options.toOdata &&
|
|
315
|
+
if (options.toOdata &&
|
|
273
316
|
options.toOdata.version === 'v4x') {
|
|
274
317
|
options.toOdata.version = 'v4';
|
|
275
318
|
options.toOdata.odataFormat = 'structured';
|
|
276
319
|
options.toOdata.odataContainment = true;
|
|
277
320
|
}
|
|
278
|
-
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
writeToFileOrDisplay(options.out, serviceName
|
|
292
|
-
}
|
|
293
|
-
// <service>.json (metadata_json)
|
|
294
|
-
if (odataResult.services[serviceName].metadata_json) {
|
|
295
|
-
writeToFileOrDisplay(options.out, serviceName + '.json', odataResult.services[serviceName].metadata_json);
|
|
296
|
-
}
|
|
321
|
+
const csn = options.directBackend ? model : compactModel(model, options);
|
|
322
|
+
const odataCsn = main.for.odata(csn, remapCmdOptions(options, options.toOdata));
|
|
323
|
+
if (options.toOdata && options.toOdata.csn) {
|
|
324
|
+
displayNamedCsn(odataCsn, 'odata_csn', options);
|
|
325
|
+
}
|
|
326
|
+
else if (options.toOdata && options.toOdata.json) {
|
|
327
|
+
const result = main.to.edm.all(odataCsn, options);
|
|
328
|
+
for (const serviceName in result)
|
|
329
|
+
writeToFileOrDisplay(options.out, `${serviceName}.json`, result[serviceName]);
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
const result = main.to.edmx.all(odataCsn, options);
|
|
333
|
+
for (const serviceName in result)
|
|
334
|
+
writeToFileOrDisplay(options.out, `${serviceName}.xml`, result[serviceName]);
|
|
297
335
|
}
|
|
298
|
-
displayNamedCsn(odataResult.csn, 'odata_csn', options);
|
|
299
336
|
return model;
|
|
300
337
|
}
|
|
301
338
|
|
|
302
339
|
// Execute the command line option '--to-rename' and display the results.
|
|
303
340
|
// Return the original model (for chaining)
|
|
304
341
|
//
|
|
305
|
-
|
|
306
|
-
|
|
342
|
+
// / THIS MUST SURVIVE IF WE REMOVE THE OLD API
|
|
343
|
+
// / DO NOT DELETE THIS TORENAME FUNCTIONALITY!!
|
|
307
344
|
function toRename( model ) {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
let storedProcedure =
|
|
311
|
-
for (
|
|
312
|
-
storedProcedure +=
|
|
345
|
+
const csn = options.directBackend ? model : compactModel(model, options);
|
|
346
|
+
const renameResult = toRenameWithCsn(csn, options);
|
|
347
|
+
let storedProcedure = `PROCEDURE RENAME_${renameResult.options.toRename.names.toUpperCase()}_TO_PLAIN LANGUAGE SQLSCRIPT AS BEGIN\n`;
|
|
348
|
+
for (const name in renameResult.rename) {
|
|
349
|
+
storedProcedure += ` --\n -- ${name}\n --\n`;
|
|
313
350
|
storedProcedure += renameResult.rename[name];
|
|
314
351
|
}
|
|
315
|
-
storedProcedure +=
|
|
316
|
-
writeToFileOrDisplay(options.out,
|
|
352
|
+
storedProcedure += 'END;\n';
|
|
353
|
+
writeToFileOrDisplay(options.out, `storedProcedure_${renameResult.options.toRename.names}_to_plain.sql`, storedProcedure, true);
|
|
317
354
|
return model;
|
|
318
355
|
}
|
|
319
356
|
|
|
320
|
-
|
|
357
|
+
// Execute the command line option 'manageConstraints' and display the results.
|
|
321
358
|
function manageConstraints( model ) {
|
|
322
359
|
const csn = options.directBackend ? model : compactModel(model, options);
|
|
323
360
|
const alterConstraintsResult = alterConstraintsWithCsn(csn, options);
|
|
324
361
|
const { src } = options.manageConstraints || {};
|
|
325
362
|
Object.keys(alterConstraintsResult).forEach((id) => {
|
|
326
363
|
const renderedConstraintStatement = alterConstraintsResult[id];
|
|
327
|
-
if(src === 'hdi')
|
|
364
|
+
if (src === 'hdi')
|
|
328
365
|
writeToFileOrDisplay(options.out, `${id}.hdbconstraint`, renderedConstraintStatement);
|
|
329
366
|
else
|
|
330
367
|
writeToFileOrDisplay(options.out, `${id}.sql`, renderedConstraintStatement);
|
|
331
|
-
})
|
|
368
|
+
});
|
|
332
369
|
}
|
|
333
370
|
|
|
334
371
|
// Execute the command line option '--to-sql' and display the results.
|
|
335
372
|
// Return the original model (for chaining)
|
|
336
373
|
function toSql( model ) {
|
|
337
374
|
const csn = options.directBackend ? model : compactModel(model, options);
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
for(let name in sqlResult[pluginName]) {
|
|
342
|
-
writeToFileOrDisplay(options.out, name + '.' + pluginName, sqlResult[pluginName][name] + '\n', true);
|
|
375
|
+
if (options.toSql && options.toSql.src === 'hdi') {
|
|
376
|
+
if (options.toSql.csn) {
|
|
377
|
+
displayNamedCsn(for_hdi(csn, remapCmdOptions(options, options.toSql)), 'hdi_csn', options);
|
|
343
378
|
}
|
|
344
|
-
|
|
345
|
-
|
|
379
|
+
else {
|
|
380
|
+
const hdiResult = main.to.hdi(csn, remapCmdOptions(options, options.toSql));
|
|
381
|
+
for (const name in hdiResult)
|
|
382
|
+
writeToFileOrDisplay(options.out, name, hdiResult[name]);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
else if (options.toSql && options.toSql.csn) {
|
|
386
|
+
displayNamedCsn(for_sql(csn, remapCmdOptions(options, options.toSql)), 'sql_csn', options);
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
const sqlResult = main.to.sql(csn, remapCmdOptions(options, options.toSql));
|
|
390
|
+
writeToFileOrDisplay(options.out, 'model.sql', sqlResult.join('\n'), true);
|
|
391
|
+
}
|
|
346
392
|
return model;
|
|
347
393
|
}
|
|
348
394
|
|
|
349
395
|
function explain() {
|
|
350
396
|
if (args.length !== 1)
|
|
351
|
-
displayUsage(
|
|
397
|
+
displayUsage('Command \'explain\' expects exactly one message-id.', optionProcessor.commands.explain.helpText, 2);
|
|
352
398
|
|
|
353
399
|
const id = args.files[0];
|
|
354
400
|
if (!hasMessageExplanation(id))
|
|
@@ -360,23 +406,24 @@ function executeCommandLine(command, options, args) {
|
|
|
360
406
|
// Display error messages in `err` resulting from a compilation. Also set
|
|
361
407
|
// process.exitCode - process.exit() will force the process to exit as quickly
|
|
362
408
|
// as possible = is problematic, since console.error() might be asynchronous
|
|
363
|
-
function displayErrors
|
|
409
|
+
function displayErrors(err) {
|
|
364
410
|
if (err instanceof main.CompilationError) {
|
|
365
411
|
if (options.rawOutput)
|
|
366
412
|
console.error( util.inspect( reveal( err.model, options.rawOutput ), false, null ));
|
|
367
413
|
else
|
|
368
|
-
displayMessages( err.model, err.
|
|
414
|
+
displayMessages( err.model, err.messages );
|
|
369
415
|
process.exitCode = 1;
|
|
370
416
|
}
|
|
371
417
|
else if (err instanceof compiler.InvocationError) {
|
|
372
418
|
console.error( '' );
|
|
373
|
-
for (
|
|
419
|
+
for (const sub of err.errors)
|
|
374
420
|
console.error( sub.message );
|
|
375
421
|
console.error( '' );
|
|
376
422
|
process.exitCode = 2;
|
|
377
423
|
}
|
|
378
|
-
else
|
|
424
|
+
else {
|
|
379
425
|
throw err;
|
|
426
|
+
}
|
|
380
427
|
|
|
381
428
|
err.hasBeenReported = true;
|
|
382
429
|
throw err;
|
|
@@ -397,11 +444,11 @@ function executeCommandLine(command, options, args) {
|
|
|
397
444
|
sortMessages(messages);
|
|
398
445
|
|
|
399
446
|
if (options.internalMsg) {
|
|
400
|
-
messages.map(msg => util.inspect( msg, { depth: null, maxArrayLength: null} ) )
|
|
447
|
+
messages.map(msg => util.inspect( msg, { depth: null, maxArrayLength: null } ) )
|
|
401
448
|
.forEach(msg => log(msg));
|
|
402
449
|
}
|
|
403
450
|
else if (options.noMessageContext) {
|
|
404
|
-
messages.filter(msg => (messageLevels[
|
|
451
|
+
messages.filter(msg => (messageLevels[msg.severity] <= options.warning))
|
|
405
452
|
.forEach(msg => log(main.messageString(msg, normalizeFilename, !options.showMessageId)));
|
|
406
453
|
}
|
|
407
454
|
else {
|
|
@@ -413,19 +460,20 @@ function executeCommandLine(command, options, args) {
|
|
|
413
460
|
return splitCache[name];
|
|
414
461
|
};
|
|
415
462
|
let hasAtLeastOneExplanation = false;
|
|
416
|
-
messages.filter(msg => messageLevels[
|
|
417
|
-
hasAtLeastOneExplanation = hasAtLeastOneExplanation || main.hasMessageExplanation(msg.messageId)
|
|
463
|
+
messages.filter(msg => messageLevels[msg.severity] <= options.warning).forEach((msg) => {
|
|
464
|
+
hasAtLeastOneExplanation = hasAtLeastOneExplanation || main.hasMessageExplanation(msg.messageId);
|
|
418
465
|
const name = msg.location && msg.location.file;
|
|
419
466
|
const fullFilePath = name ? path.resolve('', name) : undefined;
|
|
420
467
|
const context = fullFilePath && sourceLines(fullFilePath);
|
|
421
|
-
log(main.messageStringMultiline(msg, {
|
|
468
|
+
log(main.messageStringMultiline(msg, {
|
|
469
|
+
normalizeFilename, noMessageId: !options.showMessageId, withLineSpacer: true, hintExplanation: true,
|
|
470
|
+
}));
|
|
422
471
|
if (context)
|
|
423
472
|
log(main.messageContext(context, msg));
|
|
424
|
-
log() // newline
|
|
473
|
+
log(); // newline
|
|
425
474
|
});
|
|
426
|
-
if (options.showMessageId && hasAtLeastOneExplanation)
|
|
427
|
-
log(`${term.help('help')}: Messages marked with '…' have an explanation text. Use \`cdsc explain <message-id>\` for a more detailed error description.`)
|
|
428
|
-
}
|
|
475
|
+
if (options.showMessageId && hasAtLeastOneExplanation)
|
|
476
|
+
log(`${term.help('help')}: Messages marked with '…' have an explanation text. Use \`cdsc explain <message-id>\` for a more detailed error description.`);
|
|
429
477
|
}
|
|
430
478
|
return model;
|
|
431
479
|
}
|
|
@@ -436,18 +484,18 @@ function executeCommandLine(command, options, args) {
|
|
|
436
484
|
// written in raw form to '<name>_raw.txt'.
|
|
437
485
|
function displayNamedXsn(xsn, name, options) {
|
|
438
486
|
if (options.rawOutput) {
|
|
439
|
-
writeToFileOrDisplay(options.out, name
|
|
487
|
+
writeToFileOrDisplay(options.out, `${name}_raw.txt`, util.inspect(reveal(xsn, options.rawOutput), false, null), true);
|
|
440
488
|
}
|
|
441
489
|
else if (options.internalMsg) {
|
|
442
|
-
writeToFileOrDisplay(options.out, name
|
|
490
|
+
writeToFileOrDisplay(options.out, `${name}_raw.txt`, util.inspect(reveal(xsn).messages, { depth: null, maxArrayLength: null }), true);
|
|
443
491
|
}
|
|
444
492
|
else if (!options.lintMode) {
|
|
445
|
-
|
|
493
|
+
const csn = compactModel(xsn, options);
|
|
446
494
|
if (command === 'toCsn' && options.toCsn && options.toCsn.withLocalized)
|
|
447
495
|
addLocalizationViews(csn, options);
|
|
448
496
|
if (options.enrichCsn)
|
|
449
497
|
enrichCsn( csn, options );
|
|
450
|
-
writeToFileOrDisplay(options.out, name
|
|
498
|
+
writeToFileOrDisplay(options.out, `${name}.json`, csn, true);
|
|
451
499
|
}
|
|
452
500
|
}
|
|
453
501
|
|
|
@@ -460,12 +508,12 @@ function executeCommandLine(command, options, args) {
|
|
|
460
508
|
if (!csn) // only print CSN if it is set.
|
|
461
509
|
return;
|
|
462
510
|
if (options.internalMsg) {
|
|
463
|
-
writeToFileOrDisplay(options.out, name
|
|
511
|
+
writeToFileOrDisplay(options.out, `${name}_raw.txt`, options.messages, true);
|
|
464
512
|
}
|
|
465
513
|
else if (!options.lintMode && !options.internalMsg) {
|
|
466
514
|
if (command === 'toCsn' && options.toCsn && options.toCsn.withLocalized)
|
|
467
515
|
addLocalizationViews(csn, options);
|
|
468
|
-
writeToFileOrDisplay(options.out, name
|
|
516
|
+
writeToFileOrDisplay(options.out, `${name}.json`, csn, true);
|
|
469
517
|
}
|
|
470
518
|
}
|
|
471
519
|
|
|
@@ -480,28 +528,28 @@ function executeCommandLine(command, options, args) {
|
|
|
480
528
|
fileName = fileName.replace(/[:/\\]/g, '_');
|
|
481
529
|
|
|
482
530
|
// replace all dots with underscore to get deployable .hdbcds sources (except the one before the file extension)
|
|
483
|
-
if(options.
|
|
484
|
-
fileName = fileName.replace(/\.(?=.*?\.)/g, '_')
|
|
531
|
+
if (options.transformation === 'hdbcds')
|
|
532
|
+
fileName = fileName.replace(/\.(?=.*?\.)/g, '_');
|
|
485
533
|
|
|
486
|
-
if (!(content instanceof String || typeof content === 'string'))
|
|
534
|
+
if (!(content instanceof String || typeof content === 'string'))
|
|
487
535
|
content = JSON.stringify(content, null, 2);
|
|
488
|
-
|
|
536
|
+
|
|
489
537
|
if (dir === '-') {
|
|
490
|
-
if (!omitHeadline)
|
|
538
|
+
if (!omitHeadline)
|
|
491
539
|
process.stdout.write(`// ------------------- ${fileName} -------------------\n`);
|
|
492
|
-
|
|
540
|
+
|
|
493
541
|
process.stdout.write(`${content}\n`);
|
|
494
|
-
if (!omitHeadline)
|
|
495
|
-
process.stdout.write(
|
|
496
|
-
|
|
497
|
-
|
|
542
|
+
if (!omitHeadline)
|
|
543
|
+
process.stdout.write('\n');
|
|
544
|
+
}
|
|
545
|
+
else {
|
|
498
546
|
// TODO: We might consider using async file-system API ...
|
|
499
547
|
fs.writeFileSync(path.join(dir, fileName), content);
|
|
500
548
|
}
|
|
501
549
|
}
|
|
502
550
|
|
|
503
|
-
function catchErrors
|
|
504
|
-
if (err instanceof Error && err
|
|
551
|
+
function catchErrors(err) {
|
|
552
|
+
if (err instanceof Error && err.hasBeenReported)
|
|
505
553
|
return;
|
|
506
554
|
console.error( '' );
|
|
507
555
|
console.error( 'INTERNAL ERROR: %s', err );
|
package/bin/cdshi.js
CHANGED
|
@@ -16,28 +16,35 @@ const fs = require('fs');
|
|
|
16
16
|
fs.readFile( '/dev/stdin', 'utf8', highlight );
|
|
17
17
|
|
|
18
18
|
const categoryChars = {
|
|
19
|
-
artref: 'm',
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
artref: 'm',
|
|
20
|
+
paramname: 'b',
|
|
21
|
+
Entity: 'D',
|
|
22
|
+
Enum: 'H',
|
|
23
|
+
Index: 'J',
|
|
24
|
+
AnnoDef: 'V',
|
|
25
|
+
Extend: 'Z',
|
|
26
|
+
Annotate: 'Z',
|
|
27
|
+
Event: 'Y',
|
|
28
|
+
};
|
|
22
29
|
|
|
23
30
|
function highlight( err, buf ) {
|
|
24
31
|
if (err) {
|
|
25
32
|
console.error( 'ERROR:', err.toString() );
|
|
26
33
|
return;
|
|
27
34
|
}
|
|
28
|
-
|
|
35
|
+
const ts = compiler.parseX( buf, 'hi.cds', { attachTokens: true, messages: [] } ).tokenStream;
|
|
29
36
|
if (!buf.length || !ts.tokens || !ts.tokens.length)
|
|
30
37
|
return;
|
|
31
|
-
|
|
32
|
-
for (
|
|
33
|
-
|
|
38
|
+
const chars = [ ...buf ];
|
|
39
|
+
for (const tok of ts.tokens) {
|
|
40
|
+
const cat = tok.isIdentifier;
|
|
34
41
|
if (cat && tok.start >= 0) {
|
|
35
|
-
if (cat !== 'ref' || chars[
|
|
36
|
-
chars[
|
|
42
|
+
if (cat !== 'ref' || chars[tok.start] !== '$')
|
|
43
|
+
chars[tok.start] = categoryChars[cat] || cat.charAt(0);
|
|
37
44
|
if (tok.stop > tok.start) // stop in ANTLR at last char, not behind
|
|
38
|
-
chars[
|
|
45
|
+
chars[tok.start + 1] = '_';
|
|
39
46
|
}
|
|
40
47
|
}
|
|
41
|
-
for (
|
|
48
|
+
for (const c of chars)
|
|
42
49
|
process.stdout.write( c );
|
|
43
50
|
}
|