bpmnlint 11.15.0 → 12.0.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/bin/bpmnlint.js +11 -416
- package/lib/linter.js +2 -542
- package/lib/product.js +6 -0
- package/lib/resolver/helper.js +1 -12
- package/lib/resolver/node-resolver.js +6 -135
- package/lib/resolver/static-resolver.js +1 -48
- package/lib/support/compile-config.js +5 -200
- package/lib/test-rule.js +1 -107
- package/lib/testers/helper.js +14 -70
- package/lib/testers/rule-tester.d.ts +10 -28
- package/lib/testers/rule-tester.js +10 -140
- package/lib/traverse.js +1 -56
- package/lib/types.d.ts +20 -81
- package/package.json +43 -10
|
@@ -1,48 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* @typedef { import('../types.js').RuleFactory } RuleFactory
|
|
3
|
-
* @typedef { import('../types.js').Config } Config
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* A resolver that resolves rules and packages from a static cache.
|
|
9
|
-
*
|
|
10
|
-
* @param { any } cache
|
|
11
|
-
*/
|
|
12
|
-
function StaticResolver(cache) {
|
|
13
|
-
this.cache = cache;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = StaticResolver;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @param { string } pkg
|
|
20
|
-
* @param { string } ruleName
|
|
21
|
-
*
|
|
22
|
-
* @return { RuleFactory }
|
|
23
|
-
*/
|
|
24
|
-
StaticResolver.prototype.resolveRule = function(pkg, ruleName) {
|
|
25
|
-
return /** @type { RuleFactory } */ (this.resolve('rule', pkg, ruleName));
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* @param { string } pkg
|
|
30
|
-
* @param { string } configName
|
|
31
|
-
*
|
|
32
|
-
* @return { Config }
|
|
33
|
-
*/
|
|
34
|
-
StaticResolver.prototype.resolveConfig = function(pkg, configName) {
|
|
35
|
-
return /** @type { Config } */ (this.resolve('config', pkg, configName));
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
StaticResolver.prototype.resolve = function(type, pkg, name) {
|
|
39
|
-
const id = `${pkg}/${name}`;
|
|
40
|
-
|
|
41
|
-
const resolved = this.cache[`${type}:${id}`];
|
|
42
|
-
|
|
43
|
-
if (!resolved) {
|
|
44
|
-
throw new Error(`unknown ${type} <${id}>`);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return resolved;
|
|
48
|
-
};
|
|
1
|
+
module.exports = require('@bpmn-io/lint-core/lib/resolver/static-resolver');
|
|
@@ -1,201 +1,6 @@
|
|
|
1
|
-
const
|
|
1
|
+
const { createCompileConfig } = require('@bpmn-io/lint-core/lib/support/compile-config');
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const NodeResolver = require('../resolver/node-resolver');
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Compile the bpmnlint configuration to a JavaScript file that exports
|
|
11
|
-
* a { config, resolver } bundle, resolving all enabled rules.
|
|
12
|
-
*
|
|
13
|
-
* @param {Object} config the parsed bpmnlint configuration
|
|
14
|
-
* @param {NodeResolver} [resolver]
|
|
15
|
-
* @return {Promise<String>} the configuration compiled to a JS file
|
|
16
|
-
*/
|
|
17
|
-
async function compileConfig(config, resolver) {
|
|
18
|
-
|
|
19
|
-
resolver = resolver || new NodeResolver();
|
|
20
|
-
|
|
21
|
-
const linter = new Linter({
|
|
22
|
-
resolver
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
const resolvedRules = await linter.resolveConfiguredRules(config);
|
|
26
|
-
|
|
27
|
-
// only process and serialize enabled rules
|
|
28
|
-
const rules = Object.keys(resolvedRules).reduce(function(rules, key) {
|
|
29
|
-
const value = resolvedRules[key];
|
|
30
|
-
|
|
31
|
-
const { category } = linter.parseRuleValue(value);
|
|
32
|
-
|
|
33
|
-
if (category === 'off') {
|
|
34
|
-
rules[key] = 0;
|
|
35
|
-
} else {
|
|
36
|
-
rules[key] = value;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return rules;
|
|
40
|
-
}, {});
|
|
41
|
-
|
|
42
|
-
const serializedRules = JSON.stringify(rules, null, ' ');
|
|
43
|
-
|
|
44
|
-
const preambleCode = `
|
|
45
|
-
const cache = {};
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* A resolver that caches rules and configuration as part of the bundle,
|
|
49
|
-
* making them accessible in the browser.
|
|
50
|
-
*
|
|
51
|
-
* @param {Object} cache
|
|
52
|
-
*/
|
|
53
|
-
function Resolver() {}
|
|
54
|
-
|
|
55
|
-
Resolver.prototype.resolveRule = function(pkg, ruleName) {
|
|
56
|
-
|
|
57
|
-
const rule = cache[pkg + '/' + ruleName];
|
|
58
|
-
|
|
59
|
-
if (!rule) {
|
|
60
|
-
throw new Error('cannot resolve rule <' + pkg + '/' + ruleName + '>: not bundled');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return rule;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
Resolver.prototype.resolveConfig = function(pkg, configName) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
'cannot resolve config <' + configName + '> in <' + pkg +'>: not bundled'
|
|
69
|
-
);
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const resolver = new Resolver();
|
|
73
|
-
|
|
74
|
-
const rules = ${serializedRules};
|
|
75
|
-
|
|
76
|
-
const config = {
|
|
77
|
-
rules: rules
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const moddleExtensions = {};
|
|
81
|
-
|
|
82
|
-
const bundle = {
|
|
83
|
-
resolver: resolver,
|
|
84
|
-
config: config,
|
|
85
|
-
moddleExtensions: moddleExtensions
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
export { resolver, config, moddleExtensions };
|
|
89
|
-
|
|
90
|
-
export default bundle;
|
|
91
|
-
`;
|
|
92
|
-
|
|
93
|
-
const ruleImportCode = Object.entries(rules).map(([ key, value ], idx) => {
|
|
94
|
-
|
|
95
|
-
if (!value) {
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const {
|
|
100
|
-
pkg, ruleName
|
|
101
|
-
} = linter.parseRuleName(key);
|
|
102
|
-
|
|
103
|
-
return createRuleImportStatement(pkg, ruleName, idx, resolver);
|
|
104
|
-
}).filter(e => e).join('\n');
|
|
105
|
-
|
|
106
|
-
const moddleExtensionsImportCode = Object.entries(config.moddleExtensions || {}).map(([ key, importPath ], idx) => {
|
|
107
|
-
|
|
108
|
-
if (typeof importPath !== 'string') {
|
|
109
|
-
throw new Error(`illegal value for moddle-extension ${key}: expected <string>`);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return createModdleExtensionStatement(key, importPath, idx);
|
|
113
|
-
}).filter(e => e).join('\n');
|
|
114
|
-
|
|
115
|
-
return `${preambleCode}${ruleImportCode}\n${moddleExtensionsImportCode}`;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
module.exports = compileConfig;
|
|
119
|
-
|
|
120
|
-
function requirePkg(resolver, pkg) {
|
|
121
|
-
try {
|
|
122
|
-
return resolver.require(pkg);
|
|
123
|
-
} catch (err) {
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function createRuleImportStatement(pkg, ruleName, idx, resolver) {
|
|
129
|
-
const originalPkg = pkg;
|
|
130
|
-
|
|
131
|
-
pkg = resolver.normalizePkg(pkg);
|
|
132
|
-
|
|
133
|
-
const pkgExport = requirePkg(resolver, pkg);
|
|
134
|
-
|
|
135
|
-
// (1) try resolving rule via $PKG.rules[$NAME]
|
|
136
|
-
if (pkgExport && pkgExport.rules) {
|
|
137
|
-
const rules = pkgExport.rules;
|
|
138
|
-
|
|
139
|
-
if (ruleName in rules) {
|
|
140
|
-
const rule = rules[ruleName];
|
|
141
|
-
|
|
142
|
-
if (!isString(rule)) {
|
|
143
|
-
throw new Error(
|
|
144
|
-
`failed to bundle rule <${ruleName}> from <${ pkg }>: illegal rule export (expected path reference)`
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const rulePath = computeRuleImport(resolver, pkg, originalPkg, rule);
|
|
149
|
-
|
|
150
|
-
return `
|
|
151
|
-
import rule_${ idx } from '${rulePath}';
|
|
152
|
-
|
|
153
|
-
cache['${ originalPkg }/${ ruleName }'] = rule_${ idx };`;
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// (2) resolve rule via $PKG/rules/$NAME
|
|
159
|
-
return `
|
|
160
|
-
import rule_${ idx } from '${ pkg }/rules/${ ruleName }';
|
|
161
|
-
|
|
162
|
-
cache['${ originalPkg }/${ ruleName }'] = rule_${ idx };`;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* @param {string} key
|
|
168
|
-
* @param {string} importPath
|
|
169
|
-
* @param {number} idx
|
|
170
|
-
*
|
|
171
|
-
* @return {string}
|
|
172
|
-
*/
|
|
173
|
-
function createModdleExtensionStatement(key, importPath, idx) {
|
|
174
|
-
|
|
175
|
-
// (2) resolve rule via $PKG/rules/$NAME
|
|
176
|
-
return `
|
|
177
|
-
import moddle_extension_${ idx } from '${ importPath }';
|
|
178
|
-
|
|
179
|
-
moddleExtensions['${key}'] = moddle_extension_${ idx };`;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function computeRuleImport(resolver, pkg, originalPkg, rule) {
|
|
183
|
-
|
|
184
|
-
// local reference, resolved relative to pkg location
|
|
185
|
-
if (rule.startsWith('.')) {
|
|
186
|
-
const pkgJsonPath = resolver.require.resolve(`${ pkg }/package.json`);
|
|
187
|
-
|
|
188
|
-
const pkgMainPath = resolver.require.resolve(pkg);
|
|
189
|
-
|
|
190
|
-
const relativePkgMainPath = path.relative(
|
|
191
|
-
path.dirname(pkgJsonPath),
|
|
192
|
-
path.dirname(pkgMainPath)
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
return path.posix.normalize(`${ originalPkg }/${ relativePkgMainPath }/${ rule }`);
|
|
196
|
-
} else {
|
|
197
|
-
|
|
198
|
-
// absolute reference
|
|
199
|
-
return path.posix.normalize(rule);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
3
|
+
module.exports = createCompileConfig({
|
|
4
|
+
Linter: require('../linter'),
|
|
5
|
+
NodeResolver: require('../resolver/node-resolver')
|
|
6
|
+
});
|
package/lib/test-rule.js
CHANGED
|
@@ -1,107 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const {
|
|
4
|
-
isArray,
|
|
5
|
-
isObject,
|
|
6
|
-
isFunction
|
|
7
|
-
} = require('min-dash');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @typedef { import('./types.js').EnterFn } EnterFn
|
|
12
|
-
* @typedef { import('./types.js').ModdleElement } ModdleElement
|
|
13
|
-
* @typedef { import('./types.js').RuleDefinition } RuleDefinition
|
|
14
|
-
* @typedef { import('./types.js').Report } Report
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class Reporter {
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @param { {
|
|
22
|
-
* moddleRoot: ModdleElement,
|
|
23
|
-
* rule: RuleDefinition
|
|
24
|
-
* } } options
|
|
25
|
-
*/
|
|
26
|
-
constructor({ moddleRoot, rule }) {
|
|
27
|
-
this.rule = rule;
|
|
28
|
-
this.moddleRoot = moddleRoot;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @type { Report[] }
|
|
32
|
-
*/
|
|
33
|
-
this.messages = [];
|
|
34
|
-
|
|
35
|
-
this.report = this.report.bind(this);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @param { string } id
|
|
40
|
-
* @param { string } message
|
|
41
|
-
* @param { string[] | { path?: string[], [key: string]: any } } [path]
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
*
|
|
45
|
-
* ```javascript
|
|
46
|
-
* reporter.report('foo', 'Foo error', [ 'foo', 'bar', 'baz' ]);
|
|
47
|
-
*
|
|
48
|
-
* reporter.report('foo', 'Foo error', {
|
|
49
|
-
* path: [ 'foo', 'bar', 'baz' ],
|
|
50
|
-
* foo: 'foo'
|
|
51
|
-
* });
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
report(id, message, path) {
|
|
55
|
-
let report = {
|
|
56
|
-
id,
|
|
57
|
-
message
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
if (path && isArray(path)) {
|
|
61
|
-
report = {
|
|
62
|
-
...report,
|
|
63
|
-
path
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (path && isObject(path)) {
|
|
68
|
-
report = {
|
|
69
|
-
...report,
|
|
70
|
-
...path
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
this.messages.push(report);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* @param { {
|
|
80
|
-
* moddleRoot: ModdleElement,
|
|
81
|
-
* rule: RuleDefinition,
|
|
82
|
-
* config: any
|
|
83
|
-
* } } options
|
|
84
|
-
*
|
|
85
|
-
* @return { Report[] } lint reports
|
|
86
|
-
*/
|
|
87
|
-
module.exports = function testRule({ moddleRoot, rule }) {
|
|
88
|
-
const reporter = new Reporter({ rule, moddleRoot });
|
|
89
|
-
|
|
90
|
-
const check = rule.check || {};
|
|
91
|
-
|
|
92
|
-
const leave = 'leave' in check ? check.leave : undefined;
|
|
93
|
-
const enter = 'enter' in check ? check.enter : (
|
|
94
|
-
isFunction(check) ? check : undefined
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
if (!enter && !leave) {
|
|
98
|
-
throw new Error('no check implemented');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
traverse(moddleRoot, {
|
|
102
|
-
enter: enter ? (node) => enter(node, reporter) : undefined,
|
|
103
|
-
leave: leave ? (node) => leave(node, reporter) : undefined
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
return reporter.messages;
|
|
107
|
-
};
|
|
1
|
+
module.exports = require('@bpmn-io/lint-core/lib/test-rule');
|
package/lib/testers/helper.js
CHANGED
|
@@ -1,73 +1,17 @@
|
|
|
1
1
|
// @ts-expect-error 'missing <bpmn-moddle> types'
|
|
2
2
|
const { BpmnModdle } = require('bpmn-moddle');
|
|
3
3
|
|
|
4
|
-
const {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*
|
|
19
|
-
* @param {string} xml the XML string
|
|
20
|
-
* @param {string} [elementType]
|
|
21
|
-
* @param {Object} [moddleExtensions]
|
|
22
|
-
*
|
|
23
|
-
* @return {Promise<CreatedModdle>}
|
|
24
|
-
*/
|
|
25
|
-
async function createModdle(xml, elementType = 'bpmn:Definitions', moddleExtensions) {
|
|
26
|
-
|
|
27
|
-
if (typeof elementType !== 'string') {
|
|
28
|
-
moddleExtensions = elementType;
|
|
29
|
-
elementType = undefined;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (typeof elementType === 'undefined') {
|
|
33
|
-
elementType = 'bpmn:Definitions';
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const moddle = new BpmnModdle(moddleExtensions);
|
|
37
|
-
|
|
38
|
-
const {
|
|
39
|
-
rootElement: root,
|
|
40
|
-
warnings = []
|
|
41
|
-
} = await moddle.fromXML(xml, elementType, { lax: true });
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
root,
|
|
45
|
-
moddle,
|
|
46
|
-
|
|
47
|
-
// @ts-ignore-next-line "legacy"
|
|
48
|
-
context: {
|
|
49
|
-
warnings
|
|
50
|
-
},
|
|
51
|
-
warnings
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
module.exports.createModdle = createModdle;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Return moddle instance, read from the given file.
|
|
60
|
-
*
|
|
61
|
-
* @param {string|URL} filePath
|
|
62
|
-
* @param {string} [elementType]
|
|
63
|
-
* @param {Object} [moddleExtensions]
|
|
64
|
-
*
|
|
65
|
-
* @return {Promise<CreatedModdle>}
|
|
66
|
-
*/
|
|
67
|
-
function readModdle(filePath, elementType, moddleExtensions) {
|
|
68
|
-
const contents = readFileSync(filePath, 'utf8');
|
|
69
|
-
|
|
70
|
-
return createModdle(contents, elementType, moddleExtensions);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
module.exports.readModdle = readModdle;
|
|
4
|
+
const { createModdleHelper } = require('@bpmn-io/lint-core/lib/testers/helper');
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
createModdle,
|
|
8
|
+
readModdle
|
|
9
|
+
} = createModdleHelper({
|
|
10
|
+
Moddle: BpmnModdle,
|
|
11
|
+
rootType: 'bpmn:Definitions'
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
module.exports = {
|
|
15
|
+
createModdle,
|
|
16
|
+
readModdle
|
|
17
|
+
};
|
|
@@ -1,31 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
import type { RuleTests } from '@bpmn-io/lint-core/lib/testers/rule-tester';
|
|
2
2
|
|
|
3
|
-
export type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export type InvalidReport = {
|
|
13
|
-
id: string,
|
|
14
|
-
message: string
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type InvalidRuleTest = {
|
|
18
|
-
config?: any,
|
|
19
|
-
it?: TestFn,
|
|
20
|
-
moddleElement: ModdleElement,
|
|
21
|
-
name?: string,
|
|
22
|
-
report: InvalidReport | InvalidReport[]
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type RuleTests = {
|
|
26
|
-
valid?: ValidRuleTest[],
|
|
27
|
-
invalid?: InvalidRuleTest[]
|
|
28
|
-
};
|
|
3
|
+
export type {
|
|
4
|
+
TestFn,
|
|
5
|
+
ModdleElement,
|
|
6
|
+
ValidRuleTest,
|
|
7
|
+
InvalidReport,
|
|
8
|
+
InvalidRuleTest,
|
|
9
|
+
RuleTests
|
|
10
|
+
} from '@bpmn-io/lint-core/lib/testers/rule-tester';
|
|
29
11
|
|
|
30
12
|
/**
|
|
31
13
|
* Verify a rule.
|
|
@@ -34,4 +16,4 @@ export type RuleTests = {
|
|
|
34
16
|
* @param rule the rule implementation
|
|
35
17
|
* @param tests the tests to verify
|
|
36
18
|
*/
|
|
37
|
-
export function verify(ruleName: string, rule: any, tests: RuleTests): void;
|
|
19
|
+
export function verify(ruleName: string, rule: any, tests: RuleTests): void;
|
|
@@ -1,147 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
const { createRuleTester } = require('@bpmn-io/lint-core/lib/testers/rule-tester');
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
resolveConfig: () => {
|
|
13
|
-
throw new Error('not implemented');
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function expectEqual(a, b) {
|
|
19
|
-
assert.deepStrictEqual(JSON.stringify(a, replacer, 2), JSON.stringify(b, replacer, 2));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function verify(ruleName, rule, testCases) {
|
|
23
|
-
function createLinterConfig(config = {}) {
|
|
24
|
-
return {
|
|
25
|
-
rules: { [ruleName]: [ 2, config ] }
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
describe(`rules/${ruleName}`, function() {
|
|
30
|
-
|
|
31
|
-
let linter;
|
|
32
|
-
|
|
33
|
-
beforeEach(function() {
|
|
34
|
-
linter = new Linter({
|
|
35
|
-
resolver: createResolver(rule)
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
describe('should lint valid', function() {
|
|
41
|
-
|
|
42
|
-
testCases.valid.forEach(({ config = {}, it: _it, moddleElement, name }, idx) => (
|
|
43
|
-
|
|
44
|
-
(_it || it)(getTitle(idx, name), function() {
|
|
45
|
-
return (
|
|
46
|
-
Promise.resolve(moddleElement)
|
|
47
|
-
.then(moddleRoot => {
|
|
48
|
-
return linter.lint(moddleRoot.root, createLinterConfig(config));
|
|
49
|
-
})
|
|
50
|
-
.then(lintResults => {
|
|
51
|
-
expectEqual(lintResults, {});
|
|
52
|
-
})
|
|
53
|
-
);
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
));
|
|
57
|
-
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
describe('should lint invalid', function() {
|
|
62
|
-
|
|
63
|
-
testCases.invalid.forEach(({ config = {}, it: _it, moddleElement, name, report }, idx) => (
|
|
64
|
-
|
|
65
|
-
(_it || it)(getTitle(idx, name), async function() {
|
|
66
|
-
|
|
67
|
-
if (!Array.isArray(report)) {
|
|
68
|
-
report = [
|
|
69
|
-
report
|
|
70
|
-
];
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const {
|
|
74
|
-
meta
|
|
75
|
-
} = await linter.resolveRule(name, config);
|
|
76
|
-
|
|
77
|
-
const expectedResults = report.map(report => {
|
|
78
|
-
return {
|
|
79
|
-
...report,
|
|
80
|
-
meta,
|
|
81
|
-
category: 'error'
|
|
82
|
-
};
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
const expectedLintResults = {
|
|
86
|
-
[ruleName]: expectedResults
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
return (
|
|
90
|
-
Promise.resolve(moddleElement)
|
|
91
|
-
.then(moddleRoot => {
|
|
92
|
-
return linter.lint(moddleRoot.root, createLinterConfig(config));
|
|
93
|
-
})
|
|
94
|
-
.then(lintResults => {
|
|
95
|
-
expectEqual(lintResults, expectedLintResults);
|
|
96
|
-
})
|
|
97
|
-
);
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
));
|
|
101
|
-
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function getTitle(idx, name) {
|
|
109
|
-
return `test case #${ idx + 1 }${ name ? ` ${ name }` : '' }`;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function replacer(_, value) {
|
|
113
|
-
if (!value) {
|
|
114
|
-
return value;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const { $type } = value;
|
|
118
|
-
|
|
119
|
-
if ($type) {
|
|
120
|
-
const { $descriptor } = value;
|
|
121
|
-
|
|
122
|
-
const { idProperty } = $descriptor;
|
|
123
|
-
|
|
124
|
-
if (idProperty) {
|
|
125
|
-
const { name } = idProperty;
|
|
126
|
-
|
|
127
|
-
const id = value.get(name);
|
|
128
|
-
|
|
129
|
-
if (id) {
|
|
130
|
-
return id;
|
|
131
|
-
} else {
|
|
132
|
-
return $type;
|
|
133
|
-
}
|
|
134
|
-
} else {
|
|
135
|
-
return $type;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return value;
|
|
140
|
-
}
|
|
3
|
+
const {
|
|
4
|
+
expectEqual,
|
|
5
|
+
verify,
|
|
6
|
+
getTitle,
|
|
7
|
+
replacer
|
|
8
|
+
} = createRuleTester({
|
|
9
|
+
Linter: require('../linter')
|
|
10
|
+
});
|
|
141
11
|
|
|
142
12
|
module.exports = {
|
|
143
13
|
expectEqual,
|
|
144
14
|
verify,
|
|
145
15
|
getTitle,
|
|
146
16
|
replacer
|
|
147
|
-
};
|
|
17
|
+
};
|
package/lib/traverse.js
CHANGED
|
@@ -1,56 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* @typedef { import('./types.js').ModdleElement } ModdleElement
|
|
3
|
-
*
|
|
4
|
-
* @typedef { (element: ModdleElement) => boolean | void } EnterFn
|
|
5
|
-
* @typedef { (element: ModdleElement) => void } LeaveFn
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Check if a type is simple, primitive.
|
|
10
|
-
*
|
|
11
|
-
* @param {string} type
|
|
12
|
-
* @return {boolean}
|
|
13
|
-
*/
|
|
14
|
-
function isSimpleType(type) {
|
|
15
|
-
return [ 'String', 'Boolean', 'Integer', 'Real' ].includes(type);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Traverse a moddle tree, depth first from top to bottom
|
|
20
|
-
* and call the passed visitor fn.
|
|
21
|
-
*
|
|
22
|
-
* @param { ModdleElement } element
|
|
23
|
-
* @param { { enter?: EnterFn; leave?: LeaveFn } } options
|
|
24
|
-
*/
|
|
25
|
-
module.exports = function traverse(element, options) {
|
|
26
|
-
|
|
27
|
-
const enter = options.enter;
|
|
28
|
-
const leave = options.leave;
|
|
29
|
-
|
|
30
|
-
const enterSubTree = enter && enter(element);
|
|
31
|
-
|
|
32
|
-
const descriptor = element.$descriptor;
|
|
33
|
-
|
|
34
|
-
if (enterSubTree !== false && !descriptor.isGeneric) {
|
|
35
|
-
|
|
36
|
-
const containedProperties = descriptor.properties.filter(p => {
|
|
37
|
-
return !p.isAttr && !p.isReference && !isSimpleType(p.type);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
containedProperties.forEach(p => {
|
|
41
|
-
if (p.name in element) {
|
|
42
|
-
const propertyValue = element[p.name];
|
|
43
|
-
|
|
44
|
-
if (p.isMany) {
|
|
45
|
-
propertyValue.forEach(child => {
|
|
46
|
-
traverse(child, options);
|
|
47
|
-
});
|
|
48
|
-
} else {
|
|
49
|
-
traverse(propertyValue, options);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
leave && leave(element);
|
|
56
|
-
};
|
|
1
|
+
module.exports = require('@bpmn-io/lint-core/lib/traverse');
|