@sap/cds-compiler 6.9.1 → 6.9.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 +10 -0
- package/lib/api/main.js +7 -2
- package/lib/base/messages.js +7 -2
- package/lib/base/trace.js +74 -20
- package/lib/main.js +18 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -13,6 +13,16 @@ we might not list every change in its behavior here.
|
|
|
13
13
|
Productive code should never require a `beta` flag to be set, and
|
|
14
14
|
might use a deprecated flag only for a limited period of time.
|
|
15
15
|
|
|
16
|
+
## Version 6.9.2 - 2026-05-08
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
- **api:** when the environment variable `CDSC_TRACE_API` is set,
|
|
21
|
+
the compiler writes a trace for calls of API functions;
|
|
22
|
+
it now has more information, and also traces the exit of the API function.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
16
26
|
## Version 6.9.1 - 2026-05-05
|
|
17
27
|
|
|
18
28
|
### Bug Fixes
|
package/lib/api/main.js
CHANGED
|
@@ -1169,7 +1169,7 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
1169
1169
|
* @returns {any} What ever the processor returns
|
|
1170
1170
|
*/
|
|
1171
1171
|
function api( csn, options = {}, ...args ) {
|
|
1172
|
-
trace.
|
|
1172
|
+
trace.call(_name, options, csn);
|
|
1173
1173
|
const originalMessageLength = options.messages?.length;
|
|
1174
1174
|
try {
|
|
1175
1175
|
const messageFunctions = messages.makeMessageFunction(csn, options, _name);
|
|
@@ -1184,6 +1184,7 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
1184
1184
|
timetrace.timetrace.start(_name);
|
|
1185
1185
|
const result = processor( csn, options, messageFunctions, ...args );
|
|
1186
1186
|
timetrace.timetrace.stop(_name);
|
|
1187
|
+
trace.exit(_name, result);
|
|
1187
1188
|
return result;
|
|
1188
1189
|
}
|
|
1189
1190
|
catch (err) {
|
|
@@ -1200,6 +1201,7 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
1200
1201
|
if (originalMessageLength !== undefined)
|
|
1201
1202
|
options.messages.length = originalMessageLength;
|
|
1202
1203
|
|
|
1204
|
+
trace.log( 'recompile CSN and retry backend' );
|
|
1203
1205
|
const messageFunctions = messages.makeMessageFunction( csn, options, _name );
|
|
1204
1206
|
const recompileMsg = messageFunctions.info( 'api-recompiled-csn', location.emptyLocation('csn.json'), {},
|
|
1205
1207
|
'CSN input had to be recompiled' );
|
|
@@ -1211,7 +1213,10 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
1211
1213
|
const xsn = compiler.recompileX(csn, options);
|
|
1212
1214
|
const recompiledCsn = toCsn.compactModel(xsn);
|
|
1213
1215
|
messageFunctions.setModel(recompiledCsn);
|
|
1214
|
-
|
|
1216
|
+
const result = processor( recompiledCsn, options, messageFunctions, ...args );
|
|
1217
|
+
timetrace.timetrace.stop(_name);
|
|
1218
|
+
trace.exit(_name, result);
|
|
1219
|
+
return result;
|
|
1215
1220
|
}
|
|
1216
1221
|
}
|
|
1217
1222
|
}
|
package/lib/base/messages.js
CHANGED
|
@@ -16,6 +16,7 @@ const {
|
|
|
16
16
|
const _messageIdsWithExplanation = require('../../share/messages/message-explanations.json').messages;
|
|
17
17
|
const { analyseCsnPath, traverseQuery } = require('../base/csnRefs');
|
|
18
18
|
const { CompilerAssertion } = require('./error');
|
|
19
|
+
const trace = require('./trace');
|
|
19
20
|
const { getArtifactName } = require('../compiler/base');
|
|
20
21
|
const { cdlNewLineRegEx } = require('../language/textUtils');
|
|
21
22
|
const meta = require('./meta');
|
|
@@ -567,8 +568,10 @@ function makeMessageFunction( model, options, _moduleName = null ) {
|
|
|
567
568
|
}
|
|
568
569
|
|
|
569
570
|
function throwWithError() {
|
|
570
|
-
if (hasNewError)
|
|
571
|
+
if (hasNewError) {
|
|
572
|
+
trace.log( `stop compilation with ${ messages.length } messages` );
|
|
571
573
|
throw new CompilationError(messages, options.attachValidNames && model);
|
|
574
|
+
}
|
|
572
575
|
}
|
|
573
576
|
|
|
574
577
|
/**
|
|
@@ -583,8 +586,10 @@ function makeMessageFunction( model, options, _moduleName = null ) {
|
|
|
583
586
|
if (!messages || !messages.length)
|
|
584
587
|
return;
|
|
585
588
|
const hasError = options.testMode ? hasNonDowngradableErrors : hasErrors;
|
|
586
|
-
if (hasError( messages, moduleName, options ))
|
|
589
|
+
if (hasError( messages, moduleName, options )) {
|
|
590
|
+
trace.log( `stop compilation with ${ messages.length } messages` );
|
|
587
591
|
throw new CompilationError(messages, options.attachValidNames && model);
|
|
592
|
+
}
|
|
588
593
|
}
|
|
589
594
|
|
|
590
595
|
/**
|
package/lib/base/trace.js
CHANGED
|
@@ -5,33 +5,87 @@ const shouldTraceApi = process?.env?.CDSC_TRACE_API;
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Placeholder for disabled tracing (no-op).
|
|
8
|
-
*
|
|
9
|
-
* @param {string} apiName API name
|
|
10
|
-
* @param {object} options Options passed to the API.
|
|
11
|
-
* @param {...any} [args] Arguments to be logged to stderr
|
|
12
8
|
*/
|
|
13
|
-
|
|
14
|
-
function noOp( apiName, options, ...args ) {
|
|
9
|
+
function noOp() {
|
|
15
10
|
// no-op
|
|
16
11
|
}
|
|
17
12
|
|
|
18
13
|
/**
|
|
19
|
-
* Print
|
|
20
|
-
*
|
|
21
|
-
* @param {string} apiName API name
|
|
22
|
-
* @param {object} options Options passed to the API.
|
|
23
|
-
* @param {...any} [args] Arguments to be logged to stderr
|
|
14
|
+
* Print trace info to stderr when calling an API function
|
|
24
15
|
*/
|
|
25
|
-
function
|
|
26
|
-
const optStr = typeof options === 'object' ? JSON.stringify(options, null, 2) : options;
|
|
27
|
-
const argsStr = args.map(val => JSON.stringify(val)).join(', ');
|
|
28
|
-
const rest = args.length > 0 ? ` | ${ argsStr }` : '';
|
|
29
|
-
// Local require: Only load on-demand, not when tracing is disabled.
|
|
16
|
+
function call( apiName, options, csn, files ) {
|
|
30
17
|
const { version } = require('../../package.json');
|
|
18
|
+
const now = (new Date( Date.now() )).toISOString();
|
|
19
|
+
const args = (files || csn)
|
|
20
|
+
? `${ optionsString( options ) } on ${ filesInfo( files ) || csnInfo( csn ) }`
|
|
21
|
+
: optionsString( options );
|
|
31
22
|
// eslint-disable-next-line no-console
|
|
32
|
-
console.error(
|
|
23
|
+
console.error( 'CDSC_TRACE_API: at %s, call %s() of v%s with options %s',
|
|
24
|
+
now, apiName, version, args );
|
|
33
25
|
}
|
|
34
26
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Print trace info to stderr when exiting an API function
|
|
29
|
+
*/
|
|
30
|
+
function exit( apiName, result ) {
|
|
31
|
+
const now = (new Date( Date.now() )).toISOString();
|
|
32
|
+
const info = (result?.definitions || result?.extensions)
|
|
33
|
+
? csnInfo( result )
|
|
34
|
+
: `a result of type ${ typeof result }`;
|
|
35
|
+
// eslint-disable-next-line no-console
|
|
36
|
+
console.error( 'CDSC_TRACE_API: at %s, exit %s() and return %s',
|
|
37
|
+
now, apiName, info );
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Print trace info to stderr for miscellaneous use cases
|
|
42
|
+
*/
|
|
43
|
+
function log( info ) {
|
|
44
|
+
const now = (new Date( Date.now() )).toISOString();
|
|
45
|
+
// eslint-disable-next-line no-console
|
|
46
|
+
console.error( 'CDSC_TRACE_API: at %s, %s', now, info );
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function optionsString( obj ) {
|
|
50
|
+
if (!obj || typeof obj !== 'object')
|
|
51
|
+
return obj.toString();
|
|
52
|
+
try {
|
|
53
|
+
if (Array.isArray( obj.messages ) && obj.messages.length) {
|
|
54
|
+
const messages = {};
|
|
55
|
+
for (const msg of obj.messages)
|
|
56
|
+
messages[msg.severity] = (messages[msg.severity] || 0) + 1;
|
|
57
|
+
obj = { ...obj, messages };
|
|
58
|
+
}
|
|
59
|
+
return JSON.stringify( obj, null, 2 );
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
return err.toString();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function filesInfo( files ) {
|
|
67
|
+
if (!files)
|
|
68
|
+
return files;
|
|
69
|
+
if (!Array.isArray( files ))
|
|
70
|
+
files = Object.keys( files );
|
|
71
|
+
return files.length ? [ 'files', ...files ].join( '\n ') : 'no files';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function csnInfo( csn ) {
|
|
75
|
+
if (!csn || typeof csn !== 'object' || Array.isArray( csn ))
|
|
76
|
+
return `some value of type ${ typeof csn }`;
|
|
77
|
+
try {
|
|
78
|
+
JSON.stringify( csn );
|
|
79
|
+
const defs = csn.definitions ? Object.keys( csn.definitions ).length : 'no';
|
|
80
|
+
const exts = csn.extensions ? csn.extensions.length : 'no';
|
|
81
|
+
const flavor = csn.meta?.flavor || csn.meta?.compilerCsnFlavor || 'unknown';
|
|
82
|
+
return `a CSN of flavor '${ flavor }' with ${ defs } definitions and ${ exts } extensions`;
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
return `a CORRUPTED CSN (${ err.toString() })`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = (shouldTraceApi)
|
|
90
|
+
? { call, exit, log }
|
|
91
|
+
: { call: noOp, exit: noOp, log: noOp };
|
package/lib/main.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
const lazyload = require('./utils/lazyload')( module );
|
|
18
18
|
|
|
19
|
-
const
|
|
19
|
+
const trace = require('./base/trace');
|
|
20
20
|
|
|
21
21
|
const snapi = lazyload('./api/main');
|
|
22
22
|
const csnUtils = lazyload('./model/csnUtils');
|
|
@@ -40,6 +40,7 @@ const meta = lazyload('./base/meta');
|
|
|
40
40
|
const toCsn = lazyload('./json/to-csn');
|
|
41
41
|
|
|
42
42
|
function parseCdl( cdlSource, filename, options = {} ) {
|
|
43
|
+
trace.call( 'parse.cdl', options );
|
|
43
44
|
options = Object.assign( {}, options, { parseCdl: true } );
|
|
44
45
|
const sources = Object.create(null);
|
|
45
46
|
/** @type {XSN.Model} */
|
|
@@ -56,7 +57,7 @@ function parseCdl( cdlSource, filename, options = {} ) {
|
|
|
56
57
|
define( model );
|
|
57
58
|
finalizeParseCdl( model );
|
|
58
59
|
messageFunctions.throwWithError();
|
|
59
|
-
return
|
|
60
|
+
return compactAndTrace( model, 'parse.cdl' );
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
function parseCql( cdlSource, filename = '<query>.cds', options = {} ) {
|
|
@@ -75,6 +76,12 @@ function parseExpr( cdlSource, filename = '<expr>.cds', options = {} ) {
|
|
|
75
76
|
return toCsn.compactExpr( xsn );
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
function compactAndTrace( xsn, apiName = 'compile' ) {
|
|
80
|
+
const csn = toCsn.compactModel( xsn );
|
|
81
|
+
trace.exit( apiName, csn );
|
|
82
|
+
return csn;
|
|
83
|
+
}
|
|
84
|
+
|
|
78
85
|
// FIXME: The implementation of those functions that delegate to 'backends'
|
|
79
86
|
// should probably move here
|
|
80
87
|
// ATTENTION: Keep in sync with main.d.ts!
|
|
@@ -82,16 +89,19 @@ module.exports = {
|
|
|
82
89
|
// Compiler
|
|
83
90
|
version: () => meta.version(),
|
|
84
91
|
compile: (filenames, dir, options, fileCache) => { // main function
|
|
85
|
-
|
|
86
|
-
return compiler.compileX(filenames, dir, options, fileCache)
|
|
92
|
+
trace.call( 'compile', options, null, filenames );
|
|
93
|
+
return compiler.compileX( filenames, dir, options, fileCache )
|
|
94
|
+
.then( compactAndTrace );
|
|
87
95
|
},
|
|
88
96
|
compileSync: (filenames, dir, options, fileCache) => { // main function
|
|
89
|
-
|
|
90
|
-
|
|
97
|
+
trace.call( 'compileSync', options, null, filenames );
|
|
98
|
+
const xsn = compiler.compileSyncX( filenames, dir, options, fileCache );
|
|
99
|
+
return compactAndTrace( xsn, 'compileSync' );
|
|
91
100
|
},
|
|
92
101
|
compileSources: (sourcesDict, options) => { // main function
|
|
93
|
-
|
|
94
|
-
|
|
102
|
+
trace.call( 'compileSources', options, null, sourcesDict );
|
|
103
|
+
const xsn = compiler.compileSourcesX( sourcesDict, options );
|
|
104
|
+
return compactAndTrace( xsn, 'compileSources' );
|
|
95
105
|
},
|
|
96
106
|
compactModel: csn => csn, // for easy v2 migration
|
|
97
107
|
get CompilationError() {
|