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 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 10996x 10996x 10996x 10996x 32808x 32808x 32808x 32808x 32808x 32808x 32808x 32808x 32808x 32808x 32808x 32808x 32808x 10996x 10996x 10444x 10444x 10996x 10996x 260x 260x 10996x 10996x 301x 301x 301x 301x 12x 12x 289x 289x 301x 9x 9x 280x 280x 280x 280x 280x 280x 280x 280x 280x 280x 10996x 10996x 1680x 1680x 1680x 75x 75x 35x 35x 75x 75x 75x 75x 75x 35x 35x 75x 1x 1x 74x 74x 75x 11x 11x 11x 11x 11x 74x 75x 1x 1x 1x 1x 75x 1680x 1680x 1680x 10996x 10996x | import {Issue} from "../issue"; import {ABAPRule} from "./_abap_rule"; import {BasicRuleConfig} from "./_basic_rule_config"; import * as Structures from "../abap/3_structures/structures"; import * as Expressions from "../abap/2_statements/expressions"; import * as Statements from "../abap/2_statements/statements"; import {StructureNode} from "../abap/nodes"; import {IStructure} from "../abap/3_structures/structures/_structure"; import {IStatement, Unknown} from "../abap/2_statements/statements/_statement"; import {IRuleMetadata, RuleTag} from "./_irule"; import {EditHelper} from "../edit_helper"; import {ABAPFile} from "../abap/abap_file"; export class BeginEndNamesConf extends BasicRuleConfig { } export class BeginEndNames extends ABAPRule { private conf = new BeginEndNamesConf(); public getMetadata(): IRuleMetadata { return { key: "begin_end_names", title: "Check BEGIN END names", shortDescription: `Check BEGIN OF and END OF names match, plus there must be statements between BEGIN and END`, tags: [RuleTag.Syntax, RuleTag.Quickfix, RuleTag.SingleFile], badExample: `DATA: BEGIN OF stru, field TYPE i, END OF structure_not_the_same.`, goodExample: `DATA: BEGIN OF stru, field TYPE i, END OF stru.`, }; } public getConfig() { return this.conf; } public setConfig(conf: BeginEndNamesConf) { this.conf = conf; } public runParsed(file: ABAPFile) { const output: Issue[] = []; const struc = file.getStructure(); if (struc === undefined) { return []; } const containsUnknown = file.getStatements().some(s => s.get() instanceof Unknown); if (containsUnknown === true) { return []; } output.push(...this.test(struc, Structures.Data, Statements.DataBegin, Statements.DataEnd, file)); output.push(...this.test(struc, Structures.ClassData, Statements.ClassDataBegin, Statements.ClassDataEnd, file)); output.push(...this.test(struc, Structures.Constants, Statements.ConstantBegin, Statements.ConstantEnd, file)); output.push(...this.test(struc, Structures.Statics, Statements.StaticBegin, Statements.StaticEnd, file)); output.push(...this.test(struc, Structures.TypeEnum, Statements.TypeEnumBegin, Statements.TypeEnumEnd, file)); output.push(...this.test(struc, Structures.Types, Statements.TypeBegin, Statements.TypeEnd, file)); return output; } private test(stru: StructureNode, type: new() => IStructure, b: new() => IStatement, e: new() => IStatement, file: ABAPFile): Issue[] { const output: Issue[] = []; for (const sub of stru.findAllStructuresRecursive(type)) { let begin = sub.findDirectStatements(b)[0].findFirstExpression(Expressions.NamespaceSimpleName); if (begin === undefined) { begin = sub.findDirectStatements(b)[0].findFirstExpression(Expressions.DefinitionName); } if (begin === undefined) { continue; } const first = begin.getFirstToken(); let end = sub.findDirectStatements(e)[0].findFirstExpression(Expressions.NamespaceSimpleName); if (end === undefined) { end = sub.findDirectStatements(e)[0].findFirstExpression(Expressions.DefinitionName); } if (end === undefined) { continue; } const last = end.getFirstToken(); if (first.getStr().toUpperCase() !== last.getStr().toUpperCase()) { const fix = EditHelper.replaceRange(file, last.getStart(), last.getEnd(), first.getStr()); const message = "BEGIN END names must match"; const issue = Issue.atToken(file, first, message, this.getMetadata().key, this.conf.severity, fix); output.push(issue); } if (sub.getChildren().length === 2) { const message = "There must be statements between BEGIN and END"; const issue = Issue.atToken(file, first, message, this.getMetadata().key, this.conf.severity); output.push(issue); } } return output; } } |