Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 17x 17x 17x 17x 17x 17x 1x 1x 78x 110x 62x 62x 62x 62x 62x 1x 1x 62x 110x 48x 48x 8x 8x 8x 48x 110x 78x 1x 1x 48x 48x 3x 48x 21x 45x 3x 24x 1x 21x 1x 1x 19x 19x 1x | import * as Statements from "../../2_statements/statements";
import * as Structures from "../../3_structures/structures";
import {StatementNode, StructureNode} from "../../nodes";
import {IStructure} from "../../3_structures/structures/_structure";
import {SyntaxInput, syntaxIssue} from "../_syntax_input";
type StructureType = new () => IStructure;
const LOOPS: StructureType[] = [
Structures.Loop,
Structures.LoopAtScreen,
Structures.LoopExtract,
Structures.Do,
Structures.While,
Structures.Select,
Structures.With,
Structures.Provide,
];
// a CLEANUP block cannot contain statements that statically leave it: RETURN, and EXIT, CONTINUE or CHECK
// that do not belong to a loop inside the block, these end a loop outside the TRY or the processing block
export class Cleanup {
public static runSyntax(node: StructureNode, input: SyntaxInput): void {
if (input.scope.getOpenABAP()) {
return;
}
const body = node.findDirectStructure(Structures.Body);
if (body !== undefined) {
this.walk(body, false, input);
}
}
private static walk(node: StructureNode, inLoop: boolean, input: SyntaxInput): void {
for (const child of node.getChildren()) {
if (child instanceof StructureNode) {
const stru = child.get();
// a nested CLEANUP block is checked on its own, macro definitions and test injections do not run here
if (stru instanceof Structures.Cleanup
|| stru instanceof Structures.Define
|| stru instanceof Structures.TestInjection) {
continue;
}
this.walk(child, inLoop || LOOPS.some(l => stru instanceof l), input);
} else if (child instanceof StatementNode) {
const name = this.leavingStatement(child, inLoop);
if (name !== undefined) {
const message = `${name} cannot leave a CLEANUP block`;
input.issues.push(syntaxIssue(input, child.getFirstToken(), message));
}
}
}
}
private static leavingStatement(node: StatementNode, inLoop: boolean): string | undefined {
const s = node.get();
if (s instanceof Statements.Return) {
return "RETURN";
} else if (inLoop === true) {
return undefined;
} else if (s instanceof Statements.Exit && node.findDirectTokenByText("FROM") === undefined) {
return "EXIT";
} else if (s instanceof Statements.Continue) {
return "CONTINUE";
} else if (s instanceof Statements.Check) {
return "CHECK";
}
return undefined;
}
}
|