@sap/eslint-plugin-cds 2.4.1 → 2.6.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 +31 -2
- package/README.md +2 -1
- package/lib/api/index.js +13 -12
- package/lib/conf/all.js +22 -0
- package/lib/conf/index.js +22 -0
- package/lib/conf/recommended.js +19 -0
- package/lib/constants.js +19 -16
- package/lib/index.js +11 -33
- package/lib/parser.js +169 -10
- package/lib/rules/assoc2many-ambiguous-key.js +80 -96
- package/lib/rules/auth-no-empty-restrictions.js +23 -30
- package/lib/rules/auth-use-requires.js +25 -24
- package/lib/rules/auth-valid-restrict-grant.js +87 -49
- package/lib/rules/auth-valid-restrict-keys.js +30 -23
- package/lib/rules/auth-valid-restrict-to.js +97 -52
- package/lib/rules/auth-valid-restrict-where.js +52 -42
- package/lib/rules/extension-restrictions.js +69 -0
- package/lib/rules/index.js +27 -0
- package/lib/rules/latest-cds-version.js +23 -21
- package/lib/rules/min-node-version.js +25 -24
- package/lib/rules/no-db-keywords.js +23 -31
- package/lib/rules/no-dollar-prefixed-names.js +17 -14
- package/lib/rules/no-join-on-draft.js +27 -0
- package/lib/rules/require-2many-oncond.js +11 -16
- package/lib/rules/sql-cast-suggestion.js +16 -29
- package/lib/rules/start-elements-lowercase.js +42 -44
- package/lib/rules/start-entities-uppercase.js +29 -31
- package/lib/rules/valid-csv-header.js +65 -64
- package/lib/{api/lint.d.ts → types.d.ts} +5 -7
- package/lib/utils/Cache.js +33 -0
- package/lib/utils/Colors.js +9 -0
- package/lib/utils/createRule.js +317 -0
- package/lib/utils/findFuzzy.js +87 -0
- package/lib/utils/genDocs.js +345 -0
- package/lib/utils/getConfigPath.js +33 -0
- package/lib/utils/getConfiguredFileTypes.js +10 -0
- package/lib/utils/getFileExtensions.js +8 -0
- package/lib/utils/getProjectRootPath.js +25 -0
- package/lib/utils/isConfiguredFileType.js +20 -0
- package/lib/utils/rules.js +112 -1041
- package/lib/utils/runRuleTester.js +116 -0
- package/package.json +10 -4
- package/lib/processor.js +0 -50
- package/lib/rules/no-join-on-draft-enabled-entities.js +0 -40
- package/lib/utils/fuzzySearch.js +0 -94
- package/lib/utils/helpers.js +0 -94
- package/lib/utils/jsonc.js +0 -1
- package/lib/utils/model.js +0 -393
- package/lib/utils/ruleHelpers.js +0 -199
- package/lib/utils/ruleTester.js +0 -78
- package/lib/utils/validate.js +0 -36
package/CHANGELOG.md
CHANGED
|
@@ -6,14 +6,43 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
8
8
|
|
|
9
|
+
## [2.6.0] - 2022-09-29
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Renamed rule `no-join-on-draft-enabled-entities` to `no-join-on-draft`.
|
|
14
|
+
- Expanded list of reserved keywords to check for in rule `no-db-keywords`.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- New `extension-restrictions` rule that validates extension projects' models against restrictions set by the extended SaaS app.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- Errors from rules are shown again in the console output
|
|
23
|
+
|
|
24
|
+
## [2.5.0] - 2022-08-04
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- Model Validation rules use `parsed` flavor by default (`meta.model` property)
|
|
29
|
+
- Environment rules have { model: "none" }
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- Flavor in `model` property on `meta` object of rule
|
|
34
|
+
- Context function `getNode()` returns Node with proper location
|
|
35
|
+
|
|
9
36
|
## [2.4.1] - 2022-06-17
|
|
10
37
|
|
|
11
|
-
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- Authorization rules 'auth-*'.
|
|
12
41
|
|
|
13
42
|
### Changed
|
|
14
43
|
|
|
15
44
|
- Node.js 14 is now the minimum required Node.js version. Version 12 is no longer supported.
|
|
16
|
-
|
|
45
|
+
- Default CSN flavor in rules is `parsed`.
|
|
17
46
|
|
|
18
47
|
## [2.4.0] - 2022-04-14
|
|
19
48
|
|
package/README.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# @sap/eslint-plugin-cds
|
|
2
|
-
|
|
2
|
+
[](https://standardjs.com)
|
|
3
|
+
[](https://github.tools.sap/cap/eslint-plugin-cds/actions/workflows/sync.yml)
|
|
3
4
|
|
|
4
5
|
The [ESLint](https://eslint.org) plugin includes a set of recommended [SAP Cloud Application Programming Model (CAP)](https://cap.cloud.sap) model and environment rules. The aim of CDS linting is to catch issues with CDS models and with the environment early. To use this module we recommend to install [@sap/cds-dk](https://www.npmjs.com/package/@sap/cds-dk) globally.
|
|
5
6
|
|
package/lib/api/index.js
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Our custom ESLint plugin API should:
|
|
5
5
|
* - Expose 'createRule' and 'runRuleTester' to
|
|
6
6
|
* support the addition of *custom* CDS Lint rules at runtime
|
|
7
|
-
* - Expose '
|
|
7
|
+
* - Expose 'getFileExtensions', and 'genDocs' for usage in
|
|
8
8
|
* 'cds lint' client (@sap/cds-dk)
|
|
9
9
|
* - Expose 'parserPath' for CDS Lint rule unit tests with ESLint's ruleTester
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
12
|
+
const runRuleTester = require('../utils/runRuleTester')
|
|
13
|
+
const createRule = require('../utils/createRule')
|
|
14
|
+
const genDocs = require('../utils/genDocs')
|
|
15
|
+
const getConfigPath = require('../utils/getConfigPath')
|
|
16
|
+
const getConfiguredFileTypes = require('../utils/getConfiguredFileTypes')
|
|
17
|
+
const parserPath = require.resolve('../parser')
|
|
17
18
|
|
|
18
19
|
module.exports = {
|
|
19
|
-
createRule,
|
|
20
20
|
runRuleTester,
|
|
21
|
-
|
|
22
|
-
getFileExtensions,
|
|
21
|
+
createRule,
|
|
23
22
|
genDocs,
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
getConfigPath,
|
|
24
|
+
getFileExtensions: getConfiguredFileTypes,
|
|
25
|
+
parserPath
|
|
26
|
+
}
|
package/lib/conf/all.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
'@sap/cds/assoc2many-ambiguous-key': 2,
|
|
5
|
+
'@sap/cds/auth-no-empty-restrictions': 2,
|
|
6
|
+
'@sap/cds/auth-use-requires': 1,
|
|
7
|
+
'@sap/cds/auth-valid-restrict-grant': 1,
|
|
8
|
+
'@sap/cds/auth-valid-restrict-keys': 1,
|
|
9
|
+
'@sap/cds/auth-valid-restrict-to': 'warn',
|
|
10
|
+
'@sap/cds/auth-valid-restrict-where': 'warn',
|
|
11
|
+
'@sap/cds/latest-cds-version': 'warn',
|
|
12
|
+
'@sap/cds/min-node-version': 'error',
|
|
13
|
+
'@sap/cds/no-db-keywords': 'error',
|
|
14
|
+
'@sap/cds/no-dollar-prefixed-names': 'warn',
|
|
15
|
+
'@sap/cds/no-join-on-draft': 'warn',
|
|
16
|
+
'@sap/cds/require-2many-oncond': 'error',
|
|
17
|
+
'@sap/cds/sql-cast-suggestion': 'warn',
|
|
18
|
+
'@sap/cds/start-elements-uppercase': 'warn',
|
|
19
|
+
'@sap/cds/start-entities-uppercase': 'warn',
|
|
20
|
+
'@sap/cds/valid-csv-header': 'error',
|
|
21
|
+
'@sap/cds/extension-restrictions': 'error'
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const { FILES, GLOBALS, PLUGIN_NAME } = require('../constants')
|
|
2
|
+
const { parserPath } = require('../api')
|
|
3
|
+
|
|
4
|
+
function _createConfig (config) {
|
|
5
|
+
return {
|
|
6
|
+
root: true,
|
|
7
|
+
globals: GLOBALS,
|
|
8
|
+
plugins: [PLUGIN_NAME],
|
|
9
|
+
overrides: [
|
|
10
|
+
{
|
|
11
|
+
files: FILES,
|
|
12
|
+
parser: parserPath
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
rules: config
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = {
|
|
20
|
+
all: _createConfig(require('./all')),
|
|
21
|
+
recommended: _createConfig(require('./recommended'))
|
|
22
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
'@sap/cds/assoc2many-ambiguous-key': 2,
|
|
5
|
+
'@sap/cds/auth-no-empty-restrictions': 2,
|
|
6
|
+
'@sap/cds/auth-use-requires': 1,
|
|
7
|
+
'@sap/cds/auth-valid-restrict-grant': 1,
|
|
8
|
+
'@sap/cds/auth-valid-restrict-keys': 1,
|
|
9
|
+
'@sap/cds/auth-valid-restrict-to': 1,
|
|
10
|
+
'@sap/cds/auth-valid-restrict-where': 1,
|
|
11
|
+
'@sap/cds/min-node-version': 2,
|
|
12
|
+
'@sap/cds/no-db-keywords': 2,
|
|
13
|
+
'@sap/cds/no-dollar-prefixed-names': 1,
|
|
14
|
+
'@sap/cds/no-join-on-draft': 1,
|
|
15
|
+
'@sap/cds/require-2many-oncond': 2,
|
|
16
|
+
'@sap/cds/sql-cast-suggestion': 1,
|
|
17
|
+
'@sap/cds/valid-csv-header': 1,
|
|
18
|
+
'@sap/cds/extension-restrictions': 2
|
|
19
|
+
}
|
package/lib/constants.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* This file is used to store/share any constants for this plugin:
|
|
3
|
-
* - RULE_CATEGORIES: List of plugin's rule categories (used purely as documentation labels)
|
|
4
3
|
* - DEFAULT_RULE_CATEGORY: Default rule category (must be one of plugin's rule categories)
|
|
5
4
|
* - DEFAULT_RULE_SEVERITY: Default rule severity (must be one of those define by ESLint):
|
|
6
5
|
* https://eslint.org/docs/user-guide/configuring/rules#configuring-rules
|
|
@@ -13,18 +12,21 @@
|
|
|
13
12
|
* - GLOBALS: Globals which should be exposed to ESLint by this plugin
|
|
14
13
|
*/
|
|
15
14
|
|
|
16
|
-
const
|
|
17
|
-
const DEFAULT_RULE_CATEGORY = RULE_CATEGORIES[0];
|
|
18
|
-
const DEFAULT_RULE_SEVERITY = "error";
|
|
19
|
-
const DEFAULT_RULE_TYPE = "problem";
|
|
15
|
+
const RULE_FLAVORS = ['parsed', 'inferred']
|
|
20
16
|
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
17
|
+
const DEFAULT_RULE_CATEGORY = 'Model Validation'
|
|
18
|
+
const DEFAULT_RULE_FLAVOR = RULE_FLAVORS[0]
|
|
19
|
+
const DEFAULT_RULE_SEVERITY = 'error'
|
|
20
|
+
const DEFAULT_RULE_TYPE = 'problem'
|
|
25
21
|
|
|
26
|
-
const
|
|
27
|
-
|
|
22
|
+
const PLUGIN_NAME = require('../package.json').name
|
|
23
|
+
|
|
24
|
+
const PLUGIN_SCOPE = '@sap'
|
|
25
|
+
const PLUGIN_PREFIX = `${PLUGIN_SCOPE}/cds`
|
|
26
|
+
const CUSTOM_RULES_DIR = '.cdslint'
|
|
27
|
+
|
|
28
|
+
const FILES = ['*.cds', '*.csn', '*.csv']
|
|
29
|
+
const MODEL_FILES = ['*.cds', '*.csn']
|
|
28
30
|
|
|
29
31
|
const GLOBALS = {
|
|
30
32
|
SELECT: true,
|
|
@@ -36,19 +38,20 @@ const GLOBALS = {
|
|
|
36
38
|
CDL: true,
|
|
37
39
|
CQL: true,
|
|
38
40
|
CXL: true,
|
|
39
|
-
cds: true
|
|
40
|
-
}
|
|
41
|
+
cds: true
|
|
42
|
+
}
|
|
41
43
|
|
|
42
44
|
module.exports = {
|
|
43
|
-
|
|
45
|
+
RULE_FLAVORS,
|
|
44
46
|
DEFAULT_RULE_CATEGORY,
|
|
47
|
+
DEFAULT_RULE_FLAVOR,
|
|
45
48
|
DEFAULT_RULE_SEVERITY,
|
|
46
49
|
DEFAULT_RULE_TYPE,
|
|
47
50
|
PLUGIN_NAME,
|
|
51
|
+
PLUGIN_SCOPE,
|
|
48
52
|
PLUGIN_PREFIX,
|
|
49
|
-
PROCESSOR_NAME,
|
|
50
53
|
CUSTOM_RULES_DIR,
|
|
51
54
|
FILES,
|
|
52
55
|
MODEL_FILES,
|
|
53
56
|
GLOBALS
|
|
54
|
-
}
|
|
57
|
+
}
|
package/lib/index.js
CHANGED
|
@@ -1,44 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Custom ESLint plugin:
|
|
3
3
|
* https://eslint.org/docs/developer-guide/working-with-plugins
|
|
4
|
-
* This file exposes our plugins ESLint configuration, which must:
|
|
4
|
+
* This file exposes our plugins' ESLint configuration, which must:
|
|
5
5
|
* - Expose any 'configs' for prescribed rule configuration bundles
|
|
6
6
|
* (i.e. "recommended"). See shareable configs:
|
|
7
7
|
* https://eslint.org/docs/developer-guide/shareable-configs
|
|
8
|
-
* - Expose any 'globals' for use in ESLint
|
|
9
|
-
* - Expose any 'processors' for use in ESLint
|
|
10
8
|
* - Expose any 'rules' for use in ESLint
|
|
11
9
|
*/
|
|
12
10
|
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const rules = getRules(path.join(__dirname, "rules"));
|
|
20
|
-
|
|
21
|
-
function _getConfig(configName) {
|
|
22
|
-
return {
|
|
23
|
-
globals: GLOBALS,
|
|
24
|
-
plugins: [PLUGIN_NAME],
|
|
25
|
-
overrides: [
|
|
26
|
-
{
|
|
27
|
-
files: FILES,
|
|
28
|
-
processor: PROCESSOR_NAME,
|
|
29
|
-
},
|
|
30
|
-
],
|
|
31
|
-
rules: rules[configName],
|
|
32
|
-
};
|
|
33
|
-
}
|
|
11
|
+
const api = require('./api')
|
|
12
|
+
const rules = Object.assign(
|
|
13
|
+
{},
|
|
14
|
+
...Object.entries(require('./rules')).map(([k, v]) => ({ [k]: v() }))
|
|
15
|
+
)
|
|
16
|
+
const configs = require('./conf')
|
|
34
17
|
|
|
35
18
|
module.exports = {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
processors: {
|
|
41
|
-
cds: processor,
|
|
42
|
-
},
|
|
43
|
-
rules: rules.sources,
|
|
44
|
-
};
|
|
19
|
+
configs,
|
|
20
|
+
rules,
|
|
21
|
+
...api
|
|
22
|
+
}
|
package/lib/parser.js
CHANGED
|
@@ -6,23 +6,182 @@
|
|
|
6
6
|
* optional properties services, a scopeManager, and visitorKeys
|
|
7
7
|
* - Expose default method 'parse' which should return the AST
|
|
8
8
|
* Both methods should take in the source code and an optional configuration
|
|
9
|
-
* (parserOptions).
|
|
10
|
-
* parser is only used by ESLint's ruleTester.
|
|
9
|
+
* (parserOptions).
|
|
11
10
|
*/
|
|
12
|
-
|
|
11
|
+
const cds = require('@sap/cds')
|
|
12
|
+
const Cache = require('./utils/Cache')
|
|
13
|
+
const LOG = cds.debug('lint:plugin')
|
|
14
|
+
const colors = require('./utils/Colors')
|
|
15
|
+
const { splitDefName } = require('./utils/rules')
|
|
13
16
|
|
|
14
17
|
module.exports = {
|
|
15
18
|
parse: function (code, options) {
|
|
16
|
-
return module.exports.parseForESLint(code, options).ast
|
|
19
|
+
return module.exports.parseForESLint(code, options).ast
|
|
17
20
|
},
|
|
18
|
-
|
|
19
21
|
parseForESLint: function (code) {
|
|
20
22
|
return {
|
|
21
|
-
ast:
|
|
22
|
-
services: {
|
|
23
|
+
ast: createProgramAST(code),
|
|
24
|
+
services: {
|
|
25
|
+
getParsedCsn: function () {
|
|
26
|
+
let compiledModel
|
|
27
|
+
let reflectedModel
|
|
28
|
+
const messages = []
|
|
29
|
+
try {
|
|
30
|
+
compiledModel = cds.parse(code)
|
|
31
|
+
} catch (err) {
|
|
32
|
+
// Do nothing
|
|
33
|
+
}
|
|
34
|
+
if (compiledModel) {
|
|
35
|
+
try {
|
|
36
|
+
reflectedModel = cds.linked(compiledModel)
|
|
37
|
+
if (messages) {
|
|
38
|
+
reflectedModel.messages = messages
|
|
39
|
+
}
|
|
40
|
+
} catch (err) {
|
|
41
|
+
LOG && LOG(colors.red + 'ERROR:' + colors.reset, err)
|
|
42
|
+
LOG && LOG('COMPILED', compiledModel)
|
|
43
|
+
LOG && LOG('REFLECTED', reflectedModel)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return reflectedModel
|
|
47
|
+
},
|
|
48
|
+
getInferredCsn: function () {
|
|
49
|
+
const rootPath = Cache.get('rootpath')
|
|
50
|
+
if (Cache.has('test')) {
|
|
51
|
+
return Cache.get(`model:${rootPath}`)
|
|
52
|
+
}
|
|
53
|
+
let compiledModel
|
|
54
|
+
let reflectedModel
|
|
55
|
+
cds.resolve.cache = {}
|
|
56
|
+
|
|
57
|
+
if (!Cache.has(`model:${rootPath}`) && rootPath) {
|
|
58
|
+
const roots = Cache.get(`roots:${rootPath}`)
|
|
59
|
+
const messages = []
|
|
60
|
+
if (roots) {
|
|
61
|
+
try {
|
|
62
|
+
compiledModel = cds.load(roots, {
|
|
63
|
+
cwd: rootPath,
|
|
64
|
+
sync: true,
|
|
65
|
+
locations: true,
|
|
66
|
+
messages
|
|
67
|
+
})
|
|
68
|
+
Cache.remove('errRootModel')
|
|
69
|
+
} catch (err) {
|
|
70
|
+
Cache.set('errRootModel', err)
|
|
71
|
+
}
|
|
72
|
+
if (compiledModel) {
|
|
73
|
+
reflectedModel = cds.linked(compiledModel)
|
|
74
|
+
Cache.set(`model:${Cache.get('rootpath')}`, reflectedModel)
|
|
75
|
+
if (messages) {
|
|
76
|
+
reflectedModel.messages = messages
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
reflectedModel = Cache.get(`model:${rootPath}`)
|
|
82
|
+
}
|
|
83
|
+
return reflectedModel
|
|
84
|
+
},
|
|
85
|
+
updateInferredCsn: compileModelFromDict,
|
|
86
|
+
getEnvironment: function () {
|
|
87
|
+
const options = Cache.get('options')
|
|
88
|
+
return (options && options[0] && options[0].environment) ? options[0].environment : undefined
|
|
89
|
+
},
|
|
90
|
+
getLocation: function (name, obj, model) {
|
|
91
|
+
let loc
|
|
92
|
+
const defaultLoc = {
|
|
93
|
+
start: { line: 0, column: 0 },
|
|
94
|
+
end: { line: 1, column: 0 }
|
|
95
|
+
}
|
|
96
|
+
if (obj.$location) {
|
|
97
|
+
const objLoc = obj.$location
|
|
98
|
+
if (objLoc) {
|
|
99
|
+
// CSN entry with column 0 is equivalent to 'undefined'
|
|
100
|
+
// It means that the column in that line cannot be determined,
|
|
101
|
+
// so we assign a value 1 to get a column location of 0
|
|
102
|
+
if (objLoc.col === 0) {
|
|
103
|
+
objLoc.col = 1
|
|
104
|
+
}
|
|
105
|
+
loc = defaultLoc
|
|
106
|
+
loc.start.column = objLoc.col - 1
|
|
107
|
+
loc.start.line = objLoc.line
|
|
108
|
+
let colLength = name?.length // use length of `name` property
|
|
109
|
+
// TODO bug in reflect? : `annotate` elements have an unusable index-like `name`, e.g. "1"
|
|
110
|
+
if (obj.annotate) colLength = 0
|
|
111
|
+
loc.end.column = objLoc.col - 1 + colLength
|
|
112
|
+
loc.end.line = objLoc.line
|
|
113
|
+
} else if (obj.parent) {
|
|
114
|
+
this.getLocation(name, obj.parent, model)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Empty locations default to line 0, column 0
|
|
118
|
+
if (!loc) {
|
|
119
|
+
loc = defaultLoc
|
|
120
|
+
}
|
|
121
|
+
return loc
|
|
122
|
+
},
|
|
123
|
+
getNode: function (obj) {
|
|
124
|
+
let loc
|
|
125
|
+
if (obj) {
|
|
126
|
+
let name = obj.name
|
|
127
|
+
if (['entity', 'service'].includes(obj.kind)) {
|
|
128
|
+
name = splitDefName(obj).name
|
|
129
|
+
}
|
|
130
|
+
loc = this.getLocation(name, obj)
|
|
131
|
+
}
|
|
132
|
+
return createProgramAST(code, loc)
|
|
133
|
+
}
|
|
134
|
+
},
|
|
23
135
|
scopeManager: null,
|
|
24
136
|
tokensAndComments: [],
|
|
25
|
-
visitorKeys:
|
|
26
|
-
}
|
|
137
|
+
visitorKeys: []
|
|
138
|
+
}
|
|
27
139
|
},
|
|
28
|
-
|
|
140
|
+
createProgramAST,
|
|
141
|
+
compileModelFromDict
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Generates dummy AST with just single Program node
|
|
146
|
+
* @param code Parse file contents
|
|
147
|
+
* @returns AST
|
|
148
|
+
*/
|
|
149
|
+
function createProgramAST (code, loc) {
|
|
150
|
+
loc = loc || {
|
|
151
|
+
start: {
|
|
152
|
+
line: 1,
|
|
153
|
+
column: 0
|
|
154
|
+
},
|
|
155
|
+
end: {
|
|
156
|
+
line: 1,
|
|
157
|
+
column: 0
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
type: 'Program',
|
|
162
|
+
body: [],
|
|
163
|
+
sourceType: 'module',
|
|
164
|
+
tokens: [],
|
|
165
|
+
comments: [],
|
|
166
|
+
range: [0, code.length],
|
|
167
|
+
loc
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function compileModelFromDict (dictFiles, options) {
|
|
172
|
+
let reflectedModel
|
|
173
|
+
const messages = []
|
|
174
|
+
const compiledModel = cds.compile(dictFiles, {
|
|
175
|
+
sync: true,
|
|
176
|
+
locations: true,
|
|
177
|
+
messages,
|
|
178
|
+
...options
|
|
179
|
+
})
|
|
180
|
+
if (compiledModel) {
|
|
181
|
+
reflectedModel = cds.linked(compiledModel)
|
|
182
|
+
if (messages) {
|
|
183
|
+
reflectedModel.messages = messages
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return reflectedModel
|
|
187
|
+
}
|