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 11058x 11058x 11058x 11058x 32993x 32993x 32993x 32993x 32993x 32993x 32993x 32993x 32993x 32993x 32993x 32993x 32993x 11058x 11058x 10504x 10504x 11058x 11058x 261x 261x 11058x 11058x 302x 302x 302x 302x 12x 12x 290x 290x 302x 9x 9x 281x 281x 281x 281x 281x 281x 281x 281x 281x 281x 11058x 11058x 1686x 1686x 1686x 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 1686x 1686x 1686x 11058x 11058x | 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; } } |