@sap/eslint-plugin-cds 2.5.0 → 2.6.1
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 +24 -0
- package/README.md +2 -1
- package/lib/api/index.js +9 -9
- package/lib/conf/all.js +20 -19
- package/lib/conf/index.js +10 -10
- package/lib/conf/recommended.js +17 -16
- package/lib/constants.js +16 -14
- package/lib/index.js +17 -11
- package/lib/parser.js +90 -82
- package/lib/rules/assoc2many-ambiguous-key.js +71 -70
- package/lib/rules/auth-no-empty-restrictions.js +16 -15
- package/lib/rules/auth-use-requires.js +19 -18
- package/lib/rules/auth-valid-restrict-grant.js +49 -46
- package/lib/rules/auth-valid-restrict-keys.js +19 -18
- package/lib/rules/auth-valid-restrict-to.js +68 -64
- package/lib/rules/auth-valid-restrict-where.js +44 -43
- package/lib/rules/extension-restrictions.js +69 -0
- package/lib/rules/index.js +23 -22
- package/lib/rules/latest-cds-version.js +21 -20
- package/lib/rules/min-node-version.js +22 -22
- package/lib/rules/no-db-keywords.js +21 -27
- package/lib/rules/no-dollar-prefixed-names.js +12 -11
- package/lib/rules/no-join-on-draft.js +27 -0
- package/lib/rules/require-2many-oncond.js +8 -8
- package/lib/rules/sql-cast-suggestion.js +13 -12
- package/lib/rules/start-elements-lowercase.js +42 -41
- package/lib/rules/start-entities-uppercase.js +26 -25
- package/lib/rules/valid-csv-header.js +58 -57
- package/lib/types.d.ts +1 -0
- package/lib/utils/Cache.js +17 -17
- package/lib/utils/Colors.js +8 -8
- package/lib/utils/createRule.js +172 -153
- package/lib/utils/findFuzzy.js +37 -38
- package/lib/utils/genDocs.js +224 -242
- package/lib/utils/getConfigPath.js +27 -27
- package/lib/utils/getConfiguredFileTypes.js +4 -4
- package/lib/utils/getFileExtensions.js +3 -3
- package/lib/utils/getProjectRootPath.js +25 -0
- package/lib/utils/isConfiguredFileType.js +11 -11
- package/lib/utils/rules.js +59 -59
- package/lib/utils/runRuleTester.js +76 -71
- package/package.json +7 -1
- package/lib/rules/no-join-on-draft-enabled-entities.js +0 -25
- package/lib/utils/createRuleDocs.js +0 -361
- package/lib/utils/jsonc.js +0 -1
- package/lib/utils/jsoncParser.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,30 @@ 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.1] - 2023-01-26
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Fixed rule name in ESLint config:all to `@sap/cds/start-elements-lowercase`.
|
|
14
|
+
- Allow expensive rules to be reported when running from ESLint Cli.
|
|
15
|
+
- In _auth-valid-restrict-grant_, only suggest closely related user roles.
|
|
16
|
+
- In _auth-valid-restrict-to_, only suggest `*` if other entries apart from `*` exist.
|
|
17
|
+
|
|
18
|
+
## [2.6.0] - 2022-09-29
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- Renamed rule `no-join-on-draft-enabled-entities` to `no-join-on-draft`.
|
|
23
|
+
- Expanded list of reserved keywords to check for in rule `no-db-keywords`.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- New `extension-restrictions` rule that validates extension projects' models against restrictions set by the extended SaaS app.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- Errors from rules are shown again in the console output
|
|
32
|
+
|
|
9
33
|
## [2.5.0] - 2022-08-04
|
|
10
34
|
|
|
11
35
|
### Changed
|
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,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Our custom ESLint plugin API should:
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
* - Expose 'parserPath' for CDS Lint rule unit tests with ESLint's ruleTester
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
const runRuleTester = require(
|
|
13
|
-
const createRule = require(
|
|
14
|
-
const genDocs = require(
|
|
15
|
-
const getConfigPath = require(
|
|
16
|
-
const getConfiguredFileTypes = require(
|
|
17
|
-
const parserPath = require.resolve(
|
|
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')
|
|
18
18
|
|
|
19
19
|
module.exports = {
|
|
20
20
|
runRuleTester,
|
|
@@ -22,5 +22,5 @@ module.exports = {
|
|
|
22
22
|
genDocs,
|
|
23
23
|
getConfigPath,
|
|
24
24
|
getFileExtensions: getConfiguredFileTypes,
|
|
25
|
-
parserPath
|
|
26
|
-
}
|
|
25
|
+
parserPath
|
|
26
|
+
}
|
package/lib/conf/all.js
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
3
|
module.exports = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
4
|
+
'@sap/cds/assoc2many-ambiguous-key': 2,
|
|
5
|
+
'@sap/cds/auth-no-empty-restrictions': 2,
|
|
6
|
+
'@sap/cds/auth-use-requires': 2,
|
|
7
|
+
'@sap/cds/auth-valid-restrict-grant': 2,
|
|
8
|
+
'@sap/cds/auth-valid-restrict-keys': 2,
|
|
9
|
+
'@sap/cds/auth-valid-restrict-to': 2,
|
|
10
|
+
'@sap/cds/auth-valid-restrict-where': 2,
|
|
11
|
+
'@sap/cds/latest-cds-version': 2,
|
|
12
|
+
'@sap/cds/min-node-version': 2,
|
|
13
|
+
'@sap/cds/no-db-keywords': 2,
|
|
14
|
+
'@sap/cds/no-dollar-prefixed-names': 2,
|
|
15
|
+
'@sap/cds/no-join-on-draft': 2,
|
|
16
|
+
'@sap/cds/require-2many-oncond': 2,
|
|
17
|
+
'@sap/cds/sql-cast-suggestion': 2,
|
|
18
|
+
'@sap/cds/start-elements-lowercase': 2,
|
|
19
|
+
'@sap/cds/start-entities-uppercase': 2,
|
|
20
|
+
'@sap/cds/valid-csv-header': 2,
|
|
21
|
+
'@sap/cds/extension-restrictions': 2
|
|
22
|
+
}
|
package/lib/conf/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const { FILES, GLOBALS, PLUGIN_NAME } = require(
|
|
2
|
-
const { parserPath } = require(
|
|
1
|
+
const { FILES, GLOBALS, PLUGIN_NAME } = require('../constants')
|
|
2
|
+
const { parserPath } = require('../api')
|
|
3
3
|
|
|
4
|
-
function _createConfig(config) {
|
|
4
|
+
function _createConfig (config) {
|
|
5
5
|
return {
|
|
6
6
|
root: true,
|
|
7
7
|
globals: GLOBALS,
|
|
@@ -9,14 +9,14 @@ function _createConfig(config) {
|
|
|
9
9
|
overrides: [
|
|
10
10
|
{
|
|
11
11
|
files: FILES,
|
|
12
|
-
parser: parserPath
|
|
13
|
-
}
|
|
12
|
+
parser: parserPath
|
|
13
|
+
}
|
|
14
14
|
],
|
|
15
|
-
rules: config
|
|
16
|
-
}
|
|
15
|
+
rules: config
|
|
16
|
+
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
module.exports = {
|
|
20
|
-
all: _createConfig(require(
|
|
21
|
-
recommended: _createConfig(require(
|
|
22
|
-
}
|
|
20
|
+
all: _createConfig(require('./all')),
|
|
21
|
+
recommended: _createConfig(require('./recommended'))
|
|
22
|
+
}
|
package/lib/conf/recommended.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
3
|
module.exports = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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': 1,
|
|
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
|
@@ -12,25 +12,26 @@
|
|
|
12
12
|
* - GLOBALS: Globals which should be exposed to ESLint by this plugin
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
const RULE_FLAVORS = [
|
|
15
|
+
const RULE_FLAVORS = ['parsed', 'inferred']
|
|
16
16
|
|
|
17
|
-
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'
|
|
18
21
|
|
|
19
|
-
const
|
|
20
|
-
const DEFAULT_RULE_TYPE = "problem";
|
|
22
|
+
const PLUGIN_NAME = require('../package.json').name
|
|
21
23
|
|
|
22
|
-
const
|
|
24
|
+
const PLUGIN_SCOPE = '@sap'
|
|
25
|
+
const PLUGIN_PREFIX = `${PLUGIN_SCOPE}/cds`
|
|
26
|
+
const CUSTOM_RULES_DIR = '.cdslint'
|
|
23
27
|
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const CUSTOM_RULES_DIR = ".cdslint";
|
|
27
|
-
|
|
28
|
-
const FILES = ["*.cds", "*.csn", "*.csv"];
|
|
29
|
-
const MODEL_FILES = ["*.cds", "*.csn"];
|
|
28
|
+
const FILES = ['*.cds', '*.csn', '*.csv']
|
|
29
|
+
const MODEL_FILES = ['*.cds', '*.csn']
|
|
30
30
|
|
|
31
31
|
const GLOBALS = {
|
|
32
32
|
SELECT: true,
|
|
33
33
|
INSERT: true,
|
|
34
|
+
UPSERT: true,
|
|
34
35
|
UPDATE: true,
|
|
35
36
|
DELETE: true,
|
|
36
37
|
CREATE: true,
|
|
@@ -38,11 +39,12 @@ const GLOBALS = {
|
|
|
38
39
|
CDL: true,
|
|
39
40
|
CQL: true,
|
|
40
41
|
CXL: true,
|
|
41
|
-
cds: true
|
|
42
|
-
}
|
|
42
|
+
cds: true
|
|
43
|
+
}
|
|
43
44
|
|
|
44
45
|
module.exports = {
|
|
45
46
|
RULE_FLAVORS,
|
|
47
|
+
DEFAULT_RULE_CATEGORY,
|
|
46
48
|
DEFAULT_RULE_FLAVOR,
|
|
47
49
|
DEFAULT_RULE_SEVERITY,
|
|
48
50
|
DEFAULT_RULE_TYPE,
|
|
@@ -53,4 +55,4 @@ module.exports = {
|
|
|
53
55
|
FILES,
|
|
54
56
|
MODEL_FILES,
|
|
55
57
|
GLOBALS
|
|
56
|
-
}
|
|
58
|
+
}
|
package/lib/index.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
// index.js
|
|
2
|
+
/**
|
|
3
|
+
* ## Plugin structure
|
|
4
|
+
* This is the main entry point of our [custom ESLint plugin](https://eslint.org/docs/developer-guide/working-with-plugins),
|
|
5
|
+
* which exposes sets of [rules]() along with their [severity configurations]() to the [ESLint Cli]() or [API]().
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
1
8
|
/**
|
|
2
9
|
* Custom ESLint plugin:
|
|
3
10
|
* https://eslint.org/docs/developer-guide/working-with-plugins
|
|
@@ -8,16 +15,15 @@
|
|
|
8
15
|
* - Expose any 'rules' for use in ESLint
|
|
9
16
|
*/
|
|
10
17
|
|
|
11
|
-
const api = require(
|
|
12
|
-
const rules =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const configs = require("./conf");
|
|
18
|
+
const api = require('./api')
|
|
19
|
+
const rules = Object.assign(
|
|
20
|
+
{},
|
|
21
|
+
...Object.entries(require('./rules')).map(([k, v]) => ({ [k]: v() }))
|
|
22
|
+
)
|
|
23
|
+
const configs = require('./conf')
|
|
18
24
|
|
|
19
25
|
module.exports = {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
26
|
+
configs,
|
|
27
|
+
rules,
|
|
28
|
+
...api
|
|
29
|
+
}
|
package/lib/parser.js
CHANGED
|
@@ -8,172 +8,180 @@
|
|
|
8
8
|
* Both methods should take in the source code and an optional configuration
|
|
9
9
|
* (parserOptions).
|
|
10
10
|
*/
|
|
11
|
-
const cds = require(
|
|
12
|
-
const Cache = require(
|
|
13
|
-
const LOG = cds.debug(
|
|
14
|
-
const colors = require(
|
|
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')
|
|
15
16
|
|
|
16
17
|
module.exports = {
|
|
17
18
|
parse: function (code, options) {
|
|
18
|
-
return module.exports.parseForESLint(code, options).ast
|
|
19
|
+
return module.exports.parseForESLint(code, options).ast
|
|
19
20
|
},
|
|
20
21
|
parseForESLint: function (code) {
|
|
21
22
|
return {
|
|
22
23
|
ast: createProgramAST(code),
|
|
23
24
|
services: {
|
|
24
25
|
getParsedCsn: function () {
|
|
25
|
-
let compiledModel
|
|
26
|
-
let reflectedModel
|
|
27
|
-
const messages = []
|
|
26
|
+
let compiledModel
|
|
27
|
+
let reflectedModel
|
|
28
|
+
const messages = []
|
|
28
29
|
try {
|
|
29
|
-
compiledModel = cds.parse(code)
|
|
30
|
+
compiledModel = cds.parse(code)
|
|
30
31
|
} catch (err) {
|
|
31
32
|
// Do nothing
|
|
32
33
|
}
|
|
33
34
|
if (compiledModel) {
|
|
34
35
|
try {
|
|
35
|
-
reflectedModel = cds.linked(compiledModel)
|
|
36
|
+
reflectedModel = cds.linked(compiledModel)
|
|
36
37
|
if (messages) {
|
|
37
|
-
reflectedModel.messages = messages
|
|
38
|
+
reflectedModel.messages = messages
|
|
38
39
|
}
|
|
39
40
|
} catch (err) {
|
|
40
|
-
LOG && LOG(colors.red + 'ERROR:' +
|
|
41
|
+
LOG && LOG(colors.red + 'ERROR:' + colors.reset, err)
|
|
41
42
|
LOG && LOG('COMPILED', compiledModel)
|
|
42
43
|
LOG && LOG('REFLECTED', reflectedModel)
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
|
-
return reflectedModel
|
|
46
|
+
return reflectedModel
|
|
46
47
|
},
|
|
47
|
-
getInferredCsn: function() {
|
|
48
|
-
const rootPath = Cache.get(
|
|
49
|
-
if (Cache.has(
|
|
50
|
-
return Cache.get(`model:${rootPath}`)
|
|
48
|
+
getInferredCsn: function () {
|
|
49
|
+
const rootPath = Cache.get('rootpath')
|
|
50
|
+
if (Cache.has('test')) {
|
|
51
|
+
return Cache.get(`model:${rootPath}`)
|
|
51
52
|
}
|
|
52
|
-
let compiledModel
|
|
53
|
-
let reflectedModel
|
|
54
|
-
cds.resolve.cache = {}
|
|
53
|
+
let compiledModel
|
|
54
|
+
let reflectedModel
|
|
55
|
+
cds.resolve.cache = {}
|
|
55
56
|
|
|
56
|
-
if (!Cache.has(`model:${rootPath}`)) {
|
|
57
|
-
const roots =
|
|
58
|
-
const messages = []
|
|
57
|
+
if (!Cache.has(`model:${rootPath}`) && rootPath) {
|
|
58
|
+
const roots = Cache.get(`roots:${rootPath}`)
|
|
59
|
+
const messages = []
|
|
59
60
|
if (roots) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
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
77
|
}
|
|
78
78
|
}
|
|
79
|
+
}
|
|
79
80
|
} else {
|
|
80
|
-
|
|
81
|
+
reflectedModel = Cache.get(`model:${rootPath}`)
|
|
81
82
|
}
|
|
82
|
-
return reflectedModel
|
|
83
|
+
return reflectedModel
|
|
83
84
|
},
|
|
84
85
|
updateInferredCsn: compileModelFromDict,
|
|
85
86
|
getEnvironment: function () {
|
|
86
|
-
const options = Cache.get(
|
|
87
|
+
const options = Cache.get('options')
|
|
87
88
|
return (options && options[0] && options[0].environment) ? options[0].environment : undefined
|
|
88
89
|
},
|
|
89
|
-
getLocation: function(name, obj, model) {
|
|
90
|
-
let loc
|
|
90
|
+
getLocation: function (name, obj, model) {
|
|
91
|
+
let loc
|
|
91
92
|
const defaultLoc = {
|
|
92
93
|
start: { line: 0, column: 0 },
|
|
93
|
-
end: { line: 1, column: 0 }
|
|
94
|
-
}
|
|
94
|
+
end: { line: 1, column: 0 }
|
|
95
|
+
}
|
|
95
96
|
if (obj.$location) {
|
|
96
|
-
const
|
|
97
|
-
if (
|
|
97
|
+
const objLoc = obj.$location
|
|
98
|
+
if (objLoc) {
|
|
98
99
|
// CSN entry with column 0 is equivalent to 'undefined'
|
|
99
100
|
// It means that the column in that line cannot be determined,
|
|
100
101
|
// so we assign a value 1 to get a column location of 0
|
|
101
|
-
if (
|
|
102
|
-
|
|
102
|
+
if (objLoc.col === 0) {
|
|
103
|
+
objLoc.col = 1
|
|
103
104
|
}
|
|
104
|
-
loc = defaultLoc
|
|
105
|
-
loc.start.column =
|
|
106
|
-
loc.start.line =
|
|
107
|
-
|
|
108
|
-
|
|
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
|
|
109
113
|
} else if (obj.parent) {
|
|
110
|
-
this.getLocation(name, obj.parent, model)
|
|
114
|
+
this.getLocation(name, obj.parent, model)
|
|
111
115
|
}
|
|
112
116
|
}
|
|
113
117
|
// Empty locations default to line 0, column 0
|
|
114
118
|
if (!loc) {
|
|
115
|
-
loc = defaultLoc
|
|
119
|
+
loc = defaultLoc
|
|
116
120
|
}
|
|
117
|
-
return loc
|
|
121
|
+
return loc
|
|
118
122
|
},
|
|
119
|
-
getNode: function(obj) {
|
|
120
|
-
let loc
|
|
121
|
-
if (obj
|
|
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)
|
|
123
131
|
}
|
|
124
132
|
return createProgramAST(code, loc)
|
|
125
133
|
}
|
|
126
134
|
},
|
|
127
135
|
scopeManager: null,
|
|
128
136
|
tokensAndComments: [],
|
|
129
|
-
visitorKeys: []
|
|
130
|
-
}
|
|
137
|
+
visitorKeys: []
|
|
138
|
+
}
|
|
131
139
|
},
|
|
132
140
|
createProgramAST,
|
|
133
|
-
compileModelFromDict
|
|
134
|
-
}
|
|
141
|
+
compileModelFromDict
|
|
142
|
+
}
|
|
135
143
|
|
|
136
144
|
/**
|
|
137
145
|
* Generates dummy AST with just single Program node
|
|
138
146
|
* @param code Parse file contents
|
|
139
147
|
* @returns AST
|
|
140
148
|
*/
|
|
141
|
-
function createProgramAST(code, loc) {
|
|
149
|
+
function createProgramAST (code, loc) {
|
|
142
150
|
loc = loc || {
|
|
143
151
|
start: {
|
|
144
152
|
line: 1,
|
|
145
|
-
column: 0
|
|
153
|
+
column: 0
|
|
146
154
|
},
|
|
147
155
|
end: {
|
|
148
156
|
line: 1,
|
|
149
|
-
column: 0
|
|
157
|
+
column: 0
|
|
150
158
|
}
|
|
151
|
-
}
|
|
159
|
+
}
|
|
152
160
|
return {
|
|
153
|
-
type:
|
|
161
|
+
type: 'Program',
|
|
154
162
|
body: [],
|
|
155
|
-
sourceType:
|
|
163
|
+
sourceType: 'module',
|
|
156
164
|
tokens: [],
|
|
157
165
|
comments: [],
|
|
158
166
|
range: [0, code.length],
|
|
159
167
|
loc
|
|
160
|
-
}
|
|
168
|
+
}
|
|
161
169
|
}
|
|
162
170
|
|
|
163
|
-
function compileModelFromDict(dictFiles, options) {
|
|
164
|
-
let reflectedModel
|
|
165
|
-
const messages = []
|
|
171
|
+
function compileModelFromDict (dictFiles, options) {
|
|
172
|
+
let reflectedModel
|
|
173
|
+
const messages = []
|
|
166
174
|
const compiledModel = cds.compile(dictFiles, {
|
|
167
175
|
sync: true,
|
|
168
176
|
locations: true,
|
|
169
177
|
messages,
|
|
170
|
-
...options
|
|
171
|
-
})
|
|
178
|
+
...options
|
|
179
|
+
})
|
|
172
180
|
if (compiledModel) {
|
|
173
|
-
reflectedModel = cds.linked(compiledModel)
|
|
181
|
+
reflectedModel = cds.linked(compiledModel)
|
|
174
182
|
if (messages) {
|
|
175
|
-
reflectedModel.messages = messages
|
|
183
|
+
reflectedModel.messages = messages
|
|
176
184
|
}
|
|
177
185
|
}
|
|
178
|
-
return reflectedModel
|
|
186
|
+
return reflectedModel
|
|
179
187
|
}
|