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 10893x 10893x 10893x 10893x 32501x 32501x 32501x 32501x 32501x 32501x 32501x 32501x 32501x 32501x 32501x 32501x 32501x 10893x 10893x 10345x 10345x 10893x 10893x 258x 258x 10893x 10893x 299x 299x 299x 299x 12x 12x 287x 287x 299x 9x 9x 278x 278x 278x 278x 278x 278x 278x 278x 278x 278x 10893x 10893x 1668x 1668x 1668x 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 1668x 1668x 1668x 10893x 10893x | 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; } } |