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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 11661x 11661x 11661x 11661x 11661x 34801x 34801x 34801x 34801x 34801x 34801x 34801x 11661x 11661x 1x 1x 11661x 11661x 11142x 11142x 11661x 11661x 239x 239x 11661x 11661x 264x 264x 264x 136x 136x 120x 120x 16x 136x 5x 5x 16x 136x 11x 13x 13x 10x 10x 13x 11x 136x 1x 1x 136x 5x 5x 4x 4x 5x 136x 1x 1x 1x 1x 1x 136x 1x 1x 1x 136x 264x 264x 264x 11661x 11661x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x 2x 11661x | import {Issue} from "../issue";
import {ABAPRule} from "./_abap_rule";
import * as Objects from "../objects";
import {BasicRuleConfig} from "./_basic_rule_config";
import {Class} from "../objects";
import {InfoClassDefinition} from "../abap/4_file_information/_abap_file_information";
import {RuleTag} from "./_irule";
import {ABAPFile} from "../abap/abap_file";
import {ABAPObject} from "../objects/_abap_object";
import {IncludeGraph} from "../utils/include_graph";
export class SuperclassFinalConf extends BasicRuleConfig {
}
export class SuperclassFinal extends ABAPRule {
private conf = new SuperclassFinalConf();
private graph: IncludeGraph | undefined = undefined;
public getMetadata() {
return {
key: "superclass_final",
title: "Super class final",
shortDescription: `Checks that classes which are inherited from are not declared as FINAL.`,
tags: [RuleTag.Syntax],
};
}
private getMessage(): string {
return "Superclasses cannot be FINAL";
}
public getConfig() {
return this.conf;
}
public setConfig(conf: SuperclassFinalConf) {
this.conf = conf;
}
public runParsed(file: ABAPFile, obj: ABAPObject) {
const output: Issue[] = [];
for (const definition of file.getInfo().listClassDefinitions()) {
const sup = definition.superClassName;
if (sup === undefined) {
continue;
}
let localLookup = true;
if (obj instanceof Objects.Class && file.getFilename().match(/\.clas\.abap$/)) {
localLookup = false;
}
let found: InfoClassDefinition | undefined = undefined;
if (localLookup) {
for (const f of obj.getABAPFiles()) {
found = f.getInfo().getClassDefinitionByName(sup);
if (found !== undefined) {
break;
}
}
}
if (found === undefined && obj instanceof Objects.Program) {
found = this.findInRelatedProgramIncludes(file, sup);
}
if (found === undefined) {
const clas = this.reg.getObject("CLAS", sup) as Class;
if (clas) {
found = clas.getClassDefinition();
}
}
if (found === undefined) {
const message = "Super class \"" + sup + "\" not found";
const issue = Issue.atIdentifier(definition.identifier, message, this.getMetadata().key, this.conf.severity);
output.push(issue);
continue;
}
if (found.isFinal === true) {
const issue = Issue.atIdentifier(definition.identifier, this.getMessage(), this.getMetadata().key, this.conf.severity);
output.push(issue);
}
}
return output;
}
private findInRelatedProgramIncludes(file: ABAPFile, superClassName: string): InfoClassDefinition | undefined {
if (this.graph === undefined) {
this.graph = new IncludeGraph(this.reg);
}
const mainFilenames = this.graph.listMainForInclude(file.getFilename());
if (mainFilenames.length === 0) {
return undefined;
}
for (const object of this.reg.getObjectsByType("PROG")) {
if (!(object instanceof Objects.Program)) {
continue;
}
const programFile = object.getMainABAPFile();
if (programFile === undefined) {
continue;
}
const programMainFilenames = this.graph.listMainForInclude(programFile.getFilename());
if (mainFilenames.some(filename => programMainFilenames.includes(filename)) === false) {
continue;
}
const found = programFile.getInfo().getClassDefinitionByName(superClassName);
if (found !== undefined) {
return found;
}
}
return undefined;
}
}
|