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 10999x 10999x 10999x 10999x 32817x 32817x 32817x 32817x 32817x 32817x 32817x 32817x 32817x 32817x 32817x 32817x 32817x 10999x 10999x 10447x 10447x 10999x 10999x 260x 260x 10999x 10999x 301x 301x 301x 301x 12x 12x 289x 289x 301x 9x 9x 280x 280x 280x 280x 280x 280x 280x 280x 280x 280x 10999x 10999x 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 10999x 10999x | 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; } } |