@flow-scanner/lightning-flow-scanner-core 6.4.3 → 6.5.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/README.md +2 -0
- package/index.d.ts +2 -1
- package/main/internals/internals.d.ts +2 -1
- package/main/internals/internals.js +4 -0
- package/main/libs/exportAsDetails.d.ts +1 -7
- package/main/models/FlatViolation.d.ts +7 -0
- package/main/models/FlatViolation.js +4 -0
- package/main/models/LoopRuleCommon.d.ts +2 -2
- package/main/models/LoopRuleCommon.js +8 -10
- package/main/models/RuleCommon.d.ts +14 -2
- package/main/models/RuleCommon.js +16 -2
- package/main/rules/APIVersion.d.ts +3 -3
- package/main/rules/APIVersion.js +20 -24
- package/main/rules/AutoLayout.d.ts +1 -3
- package/main/rules/AutoLayout.js +10 -20
- package/main/rules/CopyAPIName.d.ts +1 -1
- package/main/rules/CopyAPIName.js +4 -13
- package/main/rules/CyclomaticComplexity.d.ts +4 -4
- package/main/rules/CyclomaticComplexity.js +19 -27
- package/main/rules/DuplicateDMLOperation.d.ts +2 -2
- package/main/rules/DuplicateDMLOperation.js +53 -56
- package/main/rules/FlowDescription.d.ts +1 -1
- package/main/rules/FlowDescription.js +8 -12
- package/main/rules/FlowName.d.ts +2 -2
- package/main/rules/FlowName.js +12 -18
- package/main/rules/GetRecordAllFields.d.ts +1 -1
- package/main/rules/GetRecordAllFields.js +11 -21
- package/main/rules/HardcodedId.d.ts +1 -1
- package/main/rules/HardcodedId.js +4 -15
- package/main/rules/HardcodedUrl.d.ts +2 -2
- package/main/rules/HardcodedUrl.js +4 -17
- package/main/rules/InactiveFlow.d.ts +1 -1
- package/main/rules/InactiveFlow.js +7 -10
- package/main/rules/MissingFaultPath.d.ts +1 -1
- package/main/rules/MissingFaultPath.js +22 -24
- package/main/rules/MissingNullHandler.d.ts +1 -1
- package/main/rules/MissingNullHandler.js +67 -70
- package/main/rules/ProcessBuilder.d.ts +1 -3
- package/main/rules/ProcessBuilder.js +3 -7
- package/main/rules/RecursiveAfterUpdate.d.ts +1 -1
- package/main/rules/RecursiveAfterUpdate.js +29 -31
- package/main/rules/SameRecordFieldUpdates.d.ts +1 -1
- package/main/rules/SameRecordFieldUpdates.js +15 -21
- package/main/rules/TriggerOrder.d.ts +1 -1
- package/main/rules/TriggerOrder.js +8 -13
- package/main/rules/UnconnectedElement.d.ts +1 -1
- package/main/rules/UnconnectedElement.js +12 -15
- package/main/rules/UnsafeRunningContext.d.ts +1 -1
- package/main/rules/UnsafeRunningContext.js +12 -13
- package/main/rules/UnusedVariable.d.ts +1 -1
- package/main/rules/UnusedVariable.js +23 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
<p>📌<strong>Tip:</strong> To link directly to a specific rule, use the full GitHub anchor link format. Example:</p>
|
|
31
31
|
<p><em><a href="https://github.com/Flow-Scanner/lightning-flow-scanner-core#unsafe-running-context">https://github.com/Flow-Scanner/lightning-flow-scanner-core#unsafe-running-context</a></em></p>
|
|
32
32
|
|
|
33
|
+
> Want to code a new rule? → See [How to Write a Rule](docs/write-a-new-rule.md)
|
|
34
|
+
|
|
33
35
|
### Action Calls In Loop(Beta)
|
|
34
36
|
|
|
35
37
|
_[ActionCallsInLoop](https://github.com/Flow-Scanner/lightning-flow-scanner-core/tree/main/src/main/rules/ActionCallsInLoop.ts)_ - To prevent exceeding Apex governor limits, it is advisable to consolidate and bulkify your apex calls, utilizing a single action call containing a collection variable at the end of the loop.
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { IRuleDefinition } from "./main/interfaces/IRuleDefinition";
|
|
2
2
|
import type { IRulesConfig } from "./main/interfaces/IRulesConfig";
|
|
3
|
+
import type { FlatViolation } from "./main/models/FlatViolation";
|
|
3
4
|
import { Compiler } from "./main/libs/Compiler";
|
|
4
5
|
import { exportDetails } from "./main/libs/exportAsDetails";
|
|
5
6
|
import { exportSarif } from "./main/libs/exportAsSarif";
|
|
@@ -19,4 +20,4 @@ import { RuleResult } from "./main/models/RuleResult";
|
|
|
19
20
|
import { ScanResult } from "./main/models/ScanResult";
|
|
20
21
|
import { Violation } from "./main/models/Violation";
|
|
21
22
|
export { Compiler, exportDetails, exportSarif, fix, Flow, FlowAttribute, FlowElement, FlowNode, FlowResource, FlowType, FlowVariable, getBetaRules, getRules, parse, ParsedFlow, Violation, RuleResult, scan, ScanResult, };
|
|
22
|
-
export type { IRuleDefinition, IRulesConfig };
|
|
23
|
+
export type { FlatViolation, IRuleDefinition, IRulesConfig };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { IRuleDefinition } from "../interfaces/IRuleDefinition";
|
|
2
2
|
import type { IRulesConfig } from "../interfaces/IRulesConfig";
|
|
3
3
|
import { Compiler } from "../libs/Compiler";
|
|
4
|
+
import { FlatViolation } from "../models/FlatViolation";
|
|
4
5
|
import { Flow } from "../models/Flow";
|
|
5
6
|
import { FlowAttribute } from "../models/FlowAttribute";
|
|
6
7
|
import { FlowElement } from "../models/FlowElement";
|
|
@@ -13,5 +14,5 @@ import { RuleCommon } from "../models/RuleCommon";
|
|
|
13
14
|
import { RuleResult } from "../models/RuleResult";
|
|
14
15
|
import { ScanResult } from "../models/ScanResult";
|
|
15
16
|
import { Violation } from "../models/Violation";
|
|
16
|
-
export { FlowAttribute, FlowElement, FlowNode, FlowType, FlowVariable, FlowResource, Flow, Compiler, ScanResult, RuleResult, Violation, RuleCommon, ParsedFlow, };
|
|
17
|
+
export { FlatViolation, FlowAttribute, FlowElement, FlowNode, FlowType, FlowVariable, FlowResource, Flow, Compiler, ScanResult, RuleResult, Violation, RuleCommon, ParsedFlow, };
|
|
17
18
|
export type { IRuleDefinition, IRulesConfig };
|
|
@@ -12,6 +12,9 @@ _export(exports, {
|
|
|
12
12
|
get Compiler () {
|
|
13
13
|
return _Compiler.Compiler;
|
|
14
14
|
},
|
|
15
|
+
get FlatViolation () {
|
|
16
|
+
return _FlatViolation.FlatViolation;
|
|
17
|
+
},
|
|
15
18
|
get Flow () {
|
|
16
19
|
return _Flow.Flow;
|
|
17
20
|
},
|
|
@@ -50,6 +53,7 @@ _export(exports, {
|
|
|
50
53
|
}
|
|
51
54
|
});
|
|
52
55
|
const _Compiler = require("../libs/Compiler");
|
|
56
|
+
const _FlatViolation = require("../models/FlatViolation");
|
|
53
57
|
const _Flow = require("../models/Flow");
|
|
54
58
|
const _FlowAttribute = require("../models/FlowAttribute");
|
|
55
59
|
const _FlowElement = require("../models/FlowElement");
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
+
import { FlatViolation } from "../models/FlatViolation";
|
|
1
2
|
import { ScanResult } from "../models/ScanResult";
|
|
2
|
-
import { Violation } from "../models/Violation";
|
|
3
|
-
export interface FlatViolation extends Omit<Violation, 'details'> {
|
|
4
|
-
flowFile: string;
|
|
5
|
-
flowName: string;
|
|
6
|
-
ruleName: string;
|
|
7
|
-
severity: string;
|
|
8
|
-
}
|
|
9
3
|
export declare function exportDetails(results: ScanResult[], includeDetails?: boolean): FlatViolation[];
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { IRuleDefinition } from "../interfaces/IRuleDefinition";
|
|
2
|
-
import { Flow,
|
|
2
|
+
import { Flow, Violation } from "../internals/internals";
|
|
3
3
|
import { RuleCommon } from "./RuleCommon";
|
|
4
4
|
import { RuleInfo } from "./RuleInfo";
|
|
5
5
|
export declare abstract class LoopRuleCommon extends RuleCommon implements IRuleDefinition {
|
|
6
6
|
constructor(info: RuleInfo);
|
|
7
|
-
|
|
7
|
+
protected check(flow: Flow, _options: object | undefined, suppressions: Set<string>): Violation[];
|
|
8
8
|
protected abstract getStatementTypes(): string[];
|
|
9
9
|
private findLoopElements;
|
|
10
10
|
private findLoopEnd;
|
|
@@ -11,16 +11,14 @@ Object.defineProperty(exports, "LoopRuleCommon", {
|
|
|
11
11
|
const _internals = require("../internals/internals");
|
|
12
12
|
const _RuleCommon = require("./RuleCommon");
|
|
13
13
|
let LoopRuleCommon = class LoopRuleCommon extends _RuleCommon.RuleCommon {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return new _internals.RuleResult(this, results);
|
|
23
|
-
});
|
|
14
|
+
check(flow, _options, suppressions) {
|
|
15
|
+
const loopElements = this.findLoopElements(flow);
|
|
16
|
+
if (!loopElements.length) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
const statementsInLoops = this.findStatementsInLoops(flow, loopElements);
|
|
20
|
+
const results = statementsInLoops.filter((det)=>!suppressions.has(det.name)).map((det)=>new _internals.Violation(det));
|
|
21
|
+
return results;
|
|
24
22
|
}
|
|
25
23
|
findLoopElements(flow) {
|
|
26
24
|
var _flow_elements;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RuleInfo } from "./RuleInfo";
|
|
2
2
|
import * as core from "../internals/internals";
|
|
3
|
-
export declare class RuleCommon {
|
|
3
|
+
export declare abstract class RuleCommon {
|
|
4
4
|
autoFixable: boolean;
|
|
5
5
|
description: string;
|
|
6
6
|
docRefs: Array<{
|
|
@@ -17,5 +17,17 @@ export declare class RuleCommon {
|
|
|
17
17
|
constructor(info: RuleInfo, optional?: {
|
|
18
18
|
severity?: string;
|
|
19
19
|
});
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* execute() – automatic suppression
|
|
22
|
+
*/
|
|
23
|
+
execute(flow: core.Flow, options?: object, suppressions?: string[]): core.RuleResult;
|
|
24
|
+
/**
|
|
25
|
+
* Rules implement this. They should return *all* violations,
|
|
26
|
+
* NOT pre-filter suppressed ones (unless they need early-exit performance).
|
|
27
|
+
*/
|
|
28
|
+
protected abstract check(flow: core.Flow, options: object | undefined, suppressions: Set<string>): core.Violation[];
|
|
29
|
+
/**
|
|
30
|
+
* Legacy/manual suppression helper (still available for early exits)
|
|
31
|
+
*/
|
|
32
|
+
protected isSuppressed(name: string, suppressions: Set<string>): boolean;
|
|
21
33
|
}
|
|
@@ -64,12 +64,26 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
64
64
|
return newObj;
|
|
65
65
|
}
|
|
66
66
|
let RuleCommon = class RuleCommon {
|
|
67
|
-
|
|
67
|
+
/**
|
|
68
|
+
* execute() – automatic suppression
|
|
69
|
+
*/ execute(flow, options, suppressions = []) {
|
|
70
|
+
// Wildcard suppression disables entire rule
|
|
68
71
|
if (suppressions.includes("*")) {
|
|
69
72
|
return new _internals.RuleResult(this, []);
|
|
70
73
|
}
|
|
74
|
+
// Convert to Set for fast lookup
|
|
71
75
|
const suppSet = new Set(suppressions);
|
|
72
|
-
|
|
76
|
+
// Raw violations from rule
|
|
77
|
+
let violations = this.check(flow, options, suppSet);
|
|
78
|
+
// Automatically filter suppressed violations by their .name
|
|
79
|
+
violations = violations.filter((v)=>!suppSet.has(v.name));
|
|
80
|
+
// Wrap into RuleResult
|
|
81
|
+
return new _internals.RuleResult(this, violations);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Legacy/manual suppression helper (still available for early exits)
|
|
85
|
+
*/ isSuppressed(name, suppressions) {
|
|
86
|
+
return suppressions.has(name);
|
|
73
87
|
}
|
|
74
88
|
constructor(info, optional){
|
|
75
89
|
_define_property(this, "autoFixable", void 0);
|
|
@@ -3,7 +3,7 @@ import { RuleCommon } from "../models/RuleCommon";
|
|
|
3
3
|
import { IRuleDefinition } from "../interfaces/IRuleDefinition";
|
|
4
4
|
export declare class APIVersion extends RuleCommon implements IRuleDefinition {
|
|
5
5
|
constructor();
|
|
6
|
-
|
|
7
|
-
expression
|
|
8
|
-
},
|
|
6
|
+
protected check(flow: core.Flow, options: {
|
|
7
|
+
expression?: string;
|
|
8
|
+
} | undefined, _suppressions: Set<string>): core.Violation[];
|
|
9
9
|
}
|
package/main/rules/APIVersion.js
CHANGED
|
@@ -52,31 +52,27 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
52
52
|
return newObj;
|
|
53
53
|
}
|
|
54
54
|
let APIVersion = class APIVersion extends _RuleCommon.RuleCommon {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (!suppSet.has(detail.name)) {
|
|
74
|
-
results.push(detail);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
55
|
+
check(flow, options, _suppressions) {
|
|
56
|
+
let flowAPIVersionNumber = null;
|
|
57
|
+
if (flow.xmldata.apiVersion) {
|
|
58
|
+
flowAPIVersionNumber = +flow.xmldata.apiVersion;
|
|
59
|
+
}
|
|
60
|
+
// No API version
|
|
61
|
+
if (!flowAPIVersionNumber) {
|
|
62
|
+
return [
|
|
63
|
+
new _internals.Violation(new _internals.FlowAttribute("API Version <49", "apiVersion", "<49"))
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
// Custom logic
|
|
67
|
+
if (options === null || options === void 0 ? void 0 : options.expression) {
|
|
68
|
+
const isValid = new Function(`return ${flowAPIVersionNumber}${options.expression};`)();
|
|
69
|
+
if (!isValid) {
|
|
70
|
+
return [
|
|
71
|
+
new _internals.Violation(new _internals.FlowAttribute(`${flowAPIVersionNumber}`, "apiVersion", options.expression))
|
|
72
|
+
];
|
|
77
73
|
}
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
}
|
|
75
|
+
return [];
|
|
80
76
|
}
|
|
81
77
|
constructor(){
|
|
82
78
|
super({
|
|
@@ -3,7 +3,5 @@ import { RuleCommon } from "../models/RuleCommon";
|
|
|
3
3
|
import { IRuleDefinition } from "../interfaces/IRuleDefinition";
|
|
4
4
|
export declare class AutoLayout extends RuleCommon implements IRuleDefinition {
|
|
5
5
|
constructor();
|
|
6
|
-
|
|
7
|
-
expression: string;
|
|
8
|
-
}, suppressions?: string[]): core.RuleResult;
|
|
6
|
+
protected check(flow: core.Flow, _options: object | undefined): core.Violation[];
|
|
9
7
|
}
|
package/main/rules/AutoLayout.js
CHANGED
|
@@ -52,26 +52,16 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
52
52
|
return newObj;
|
|
53
53
|
}
|
|
54
54
|
let AutoLayout = class AutoLayout extends _RuleCommon.RuleCommon {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
var _CanvasMode_value_stringValue;
|
|
67
|
-
const detail = new _internals.Violation(new _internals.FlowAttribute((_CanvasMode_value_stringValue = CanvasMode === null || CanvasMode === void 0 ? void 0 : (_CanvasMode_value = CanvasMode.value) === null || _CanvasMode_value === void 0 ? void 0 : _CanvasMode_value.stringValue) !== null && _CanvasMode_value_stringValue !== void 0 ? _CanvasMode_value_stringValue : "undefined", "CanvasMode", "!== AUTO_LAYOUT_CANVAS"));
|
|
68
|
-
if (suppSet.has(detail.name)) {
|
|
69
|
-
return new _internals.RuleResult(this, []);
|
|
70
|
-
}
|
|
71
|
-
return new _internals.RuleResult(this, [
|
|
72
|
-
detail
|
|
73
|
-
]);
|
|
74
|
-
});
|
|
55
|
+
check(flow, _options) {
|
|
56
|
+
var _CanvasMode_value;
|
|
57
|
+
if (!flow.processMetadataValues) return [];
|
|
58
|
+
const CanvasMode = flow.xmldata.processMetadataValues.find((mdv)=>mdv.name === "CanvasMode");
|
|
59
|
+
const autoLayout = (CanvasMode === null || CanvasMode === void 0 ? void 0 : CanvasMode.value) && typeof CanvasMode.value === "object" && CanvasMode.value.stringValue === "AUTO_LAYOUT_CANVAS";
|
|
60
|
+
if (autoLayout) return [];
|
|
61
|
+
var _CanvasMode_value_stringValue;
|
|
62
|
+
return [
|
|
63
|
+
new _internals.Violation(new _internals.FlowAttribute((_CanvasMode_value_stringValue = CanvasMode === null || CanvasMode === void 0 ? void 0 : (_CanvasMode_value = CanvasMode.value) === null || _CanvasMode_value === void 0 ? void 0 : _CanvasMode_value.stringValue) !== null && _CanvasMode_value_stringValue !== void 0 ? _CanvasMode_value_stringValue : "undefined", "CanvasMode", "!== AUTO_LAYOUT_CANVAS"))
|
|
64
|
+
];
|
|
75
65
|
}
|
|
76
66
|
constructor(){
|
|
77
67
|
super({
|
|
@@ -3,5 +3,5 @@ import { RuleCommon } from "../models/RuleCommon";
|
|
|
3
3
|
import { IRuleDefinition } from "../interfaces/IRuleDefinition";
|
|
4
4
|
export declare class CopyAPIName extends RuleCommon implements IRuleDefinition {
|
|
5
5
|
constructor();
|
|
6
|
-
|
|
6
|
+
protected check(flow: core.Flow): core.Violation[];
|
|
7
7
|
}
|
|
@@ -52,19 +52,10 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
52
52
|
return newObj;
|
|
53
53
|
}
|
|
54
54
|
let CopyAPIName = class CopyAPIName extends _RuleCommon.RuleCommon {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
for (const element of flowElements){
|
|
60
|
-
const copyOf = new RegExp("Copy_[0-9]+_of_[A-Za-z0-9]+").test(element.name);
|
|
61
|
-
if (copyOf && !suppSet.has(element.name)) {
|
|
62
|
-
copyOfElements.push(element);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
const results = copyOfElements.map((det)=>new _internals.Violation(det));
|
|
66
|
-
return new _internals.RuleResult(this, results);
|
|
67
|
-
});
|
|
55
|
+
check(flow) {
|
|
56
|
+
const flowElements = flow.elements.filter((node)=>node instanceof _internals.FlowNode);
|
|
57
|
+
const copyOfElements = flowElements.filter((el)=>/Copy_[0-9]+_of_[A-Za-z0-9]+/.test(el.name));
|
|
58
|
+
return copyOfElements.map((el)=>new _internals.Violation(el));
|
|
68
59
|
}
|
|
69
60
|
constructor(){
|
|
70
61
|
super({
|
|
@@ -2,10 +2,10 @@ import * as core from "../internals/internals";
|
|
|
2
2
|
import { RuleCommon } from "../models/RuleCommon";
|
|
3
3
|
import { IRuleDefinition } from "../interfaces/IRuleDefinition";
|
|
4
4
|
export declare class CyclomaticComplexity extends RuleCommon implements IRuleDefinition {
|
|
5
|
-
constructor();
|
|
6
5
|
private defaultThreshold;
|
|
7
6
|
private cyclomaticComplexityUnit;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
constructor();
|
|
8
|
+
protected check(flow: core.Flow, options: {
|
|
9
|
+
threshold?: number;
|
|
10
|
+
} | undefined): core.Violation[];
|
|
11
11
|
}
|
|
@@ -65,33 +65,25 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
65
65
|
return newObj;
|
|
66
66
|
}
|
|
67
67
|
let CyclomaticComplexity = class CyclomaticComplexity extends _RuleCommon.RuleCommon {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (cyclomaticComplexity > threshold) {
|
|
88
|
-
const detail = new _internals.Violation(new _internals.FlowAttribute(`${cyclomaticComplexity}`, "CyclomaticComplexity", `>${threshold}`));
|
|
89
|
-
if (!suppSet.has(detail.name)) {
|
|
90
|
-
results.push(detail);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return new _internals.RuleResult(this, results);
|
|
94
|
-
});
|
|
68
|
+
check(flow, options) {
|
|
69
|
+
var _flow_elements, _flow_elements1;
|
|
70
|
+
const threshold = (options === null || options === void 0 ? void 0 : options.threshold) || this.defaultThreshold;
|
|
71
|
+
let cyclomaticComplexity = 1;
|
|
72
|
+
const flowDecisions = flow === null || flow === void 0 ? void 0 : (_flow_elements = flow.elements) === null || _flow_elements === void 0 ? void 0 : _flow_elements.filter((node)=>node.subtype === "decisions");
|
|
73
|
+
const flowLoops = flow === null || flow === void 0 ? void 0 : (_flow_elements1 = flow.elements) === null || _flow_elements1 === void 0 ? void 0 : _flow_elements1.filter((node)=>node.subtype === "loops");
|
|
74
|
+
for (const decision of flowDecisions || []){
|
|
75
|
+
const rules = decision.element["rules"];
|
|
76
|
+
cyclomaticComplexity += Array.isArray(rules) ? rules.length + 1 : 1;
|
|
77
|
+
}
|
|
78
|
+
var _flowLoops_length;
|
|
79
|
+
cyclomaticComplexity += (_flowLoops_length = flowLoops === null || flowLoops === void 0 ? void 0 : flowLoops.length) !== null && _flowLoops_length !== void 0 ? _flowLoops_length : 0;
|
|
80
|
+
this.cyclomaticComplexityUnit = cyclomaticComplexity;
|
|
81
|
+
if (cyclomaticComplexity > threshold) {
|
|
82
|
+
return [
|
|
83
|
+
new _internals.Violation(new _internals.FlowAttribute(`${cyclomaticComplexity}`, "CyclomaticComplexity", `>${threshold}`))
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
return [];
|
|
95
87
|
}
|
|
96
88
|
constructor(){
|
|
97
89
|
super({
|
|
@@ -3,7 +3,7 @@ import { RuleCommon } from "../models/RuleCommon";
|
|
|
3
3
|
import { IRuleDefinition } from "../interfaces/IRuleDefinition";
|
|
4
4
|
export declare class DuplicateDMLOperation extends RuleCommon implements IRuleDefinition {
|
|
5
5
|
constructor();
|
|
6
|
-
|
|
7
|
-
private flagDML;
|
|
6
|
+
protected check(flow: core.Flow, _options: object | undefined, suppressions: Set<string>): core.Violation[];
|
|
8
7
|
private findStart;
|
|
8
|
+
private flagDML;
|
|
9
9
|
}
|
|
@@ -52,64 +52,69 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
52
52
|
return newObj;
|
|
53
53
|
}
|
|
54
54
|
let DuplicateDMLOperation = class DuplicateDMLOperation extends _RuleCommon.RuleCommon {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
references.push(connector.reference);
|
|
79
|
-
}
|
|
55
|
+
check(flow, _options, suppressions) {
|
|
56
|
+
const flowElements = flow.elements.filter((node)=>node instanceof _internals.FlowNode);
|
|
57
|
+
const processedElementIndexes = [];
|
|
58
|
+
const unconnectedElementIndexes = [];
|
|
59
|
+
const DuplicateDMLOperations = [];
|
|
60
|
+
const startingNode = this.findStart(flow);
|
|
61
|
+
if (startingNode === -1) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
let dmlFlag = false;
|
|
65
|
+
let indexesToProcess = [
|
|
66
|
+
startingNode
|
|
67
|
+
];
|
|
68
|
+
do {
|
|
69
|
+
indexesToProcess = indexesToProcess.filter((index)=>!processedElementIndexes.includes(index));
|
|
70
|
+
if (indexesToProcess.length > 0) {
|
|
71
|
+
for (const [index, element] of flowElements.entries()){
|
|
72
|
+
if (indexesToProcess.includes(index)) {
|
|
73
|
+
const references = [];
|
|
74
|
+
if (element.connectors && element.connectors.length > 0) {
|
|
75
|
+
for (const connector of element.connectors){
|
|
76
|
+
if (connector.reference) {
|
|
77
|
+
references.push(connector.reference);
|
|
80
78
|
}
|
|
81
79
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
80
|
+
}
|
|
81
|
+
dmlFlag = this.flagDML(element, dmlFlag);
|
|
82
|
+
if (references.length > 0) {
|
|
83
|
+
const elementsByReferences = flowElements.filter((el)=>references.includes(el.name));
|
|
84
|
+
for (const nextElement of elementsByReferences){
|
|
85
|
+
const nextIndex = flowElements.findIndex((el)=>nextElement.name === el.name);
|
|
86
|
+
if (nextElement.subtype === "screens") {
|
|
87
|
+
if (dmlFlag && nextElement.element["allowBack"] === "true" && nextElement.element["showFooter"] === "true") {
|
|
88
|
+
if (!suppressions.has(nextElement.name)) {
|
|
89
|
+
DuplicateDMLOperations.push(nextElement);
|
|
92
90
|
}
|
|
93
91
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
92
|
+
}
|
|
93
|
+
if (!processedElementIndexes.includes(nextIndex)) {
|
|
94
|
+
indexesToProcess.push(nextIndex);
|
|
97
95
|
}
|
|
98
96
|
}
|
|
99
|
-
processedElementIndexes.push(index);
|
|
100
97
|
}
|
|
98
|
+
processedElementIndexes.push(index);
|
|
101
99
|
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
for (const index of flowElements.keys()){
|
|
103
|
+
if (!processedElementIndexes.includes(index)) {
|
|
104
|
+
unconnectedElementIndexes.push(index);
|
|
107
105
|
}
|
|
108
106
|
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
107
|
+
}
|
|
108
|
+
}while (processedElementIndexes.length + unconnectedElementIndexes.length < flowElements.length)
|
|
109
|
+
return DuplicateDMLOperations.map((det)=>new _internals.Violation(det));
|
|
110
|
+
}
|
|
111
|
+
findStart(flow) {
|
|
112
|
+
const flowElements = flow.elements.filter((node)=>node instanceof _internals.FlowNode);
|
|
113
|
+
if (flow.startElementReference) {
|
|
114
|
+
return flowElements.findIndex((n)=>n.name === flow.startElementReference);
|
|
115
|
+
} else {
|
|
116
|
+
return flowElements.findIndex((n)=>n.subtype === "start");
|
|
117
|
+
}
|
|
113
118
|
}
|
|
114
119
|
flagDML(element, dmlFlag) {
|
|
115
120
|
const dmlStatementTypes = [
|
|
@@ -125,14 +130,6 @@ let DuplicateDMLOperation = class DuplicateDMLOperation extends _RuleCommon.Rule
|
|
|
125
130
|
return dmlFlag;
|
|
126
131
|
}
|
|
127
132
|
}
|
|
128
|
-
findStart(flow) {
|
|
129
|
-
const flowElements = flow.elements.filter((node)=>node instanceof _internals.FlowNode);
|
|
130
|
-
if (flow.startElementReference) {
|
|
131
|
-
return flowElements.findIndex((n)=>n.name === flow.startElementReference);
|
|
132
|
-
} else {
|
|
133
|
-
return flowElements.findIndex((n)=>n.subtype === "start");
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
133
|
constructor(){
|
|
137
134
|
super({
|
|
138
135
|
name: "DuplicateDMLOperation",
|
|
@@ -3,5 +3,5 @@ import { RuleCommon } from "../models/RuleCommon";
|
|
|
3
3
|
import { IRuleDefinition } from "../interfaces/IRuleDefinition";
|
|
4
4
|
export declare class FlowDescription extends RuleCommon implements IRuleDefinition {
|
|
5
5
|
constructor();
|
|
6
|
-
|
|
6
|
+
protected check(flow: core.Flow, _options: object | undefined, _suppressions: Set<string>): core.Violation[];
|
|
7
7
|
}
|
|
@@ -52,18 +52,14 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
52
52
|
return newObj;
|
|
53
53
|
}
|
|
54
54
|
let FlowDescription = class FlowDescription extends _RuleCommon.RuleCommon {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return new _internals.RuleResult(this, [
|
|
64
|
-
detail
|
|
65
|
-
]);
|
|
66
|
-
});
|
|
55
|
+
check(flow, _options, _suppressions) {
|
|
56
|
+
var _flow_xmldata;
|
|
57
|
+
if ((_flow_xmldata = flow.xmldata) === null || _flow_xmldata === void 0 ? void 0 : _flow_xmldata.description) {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
return [
|
|
61
|
+
new _internals.Violation(new _internals.FlowAttribute("undefined", "description", "!==null"))
|
|
62
|
+
];
|
|
67
63
|
}
|
|
68
64
|
constructor(){
|
|
69
65
|
super({
|
package/main/rules/FlowName.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { RuleCommon } from "../models/RuleCommon";
|
|
|
3
3
|
import { IRuleDefinition } from "../interfaces/IRuleDefinition";
|
|
4
4
|
export declare class FlowName extends RuleCommon implements IRuleDefinition {
|
|
5
5
|
constructor();
|
|
6
|
-
|
|
6
|
+
protected check(flow: core.Flow, options: {
|
|
7
7
|
expression?: string;
|
|
8
|
-
},
|
|
8
|
+
} | undefined, _suppressions: Set<string>): core.Violation[];
|
|
9
9
|
}
|