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 11462x 11462x 11462x 11462x 11462x 34214x 34214x 34214x 34214x 34214x 34214x 34214x 11462x 11462x 1x 1x 11462x 11462x 10927x 10927x 11462x 11462x 247x 247x 11462x 11462x 281x 281x 281x 139x 139x 123x 123x 16x 139x 5x 5x 16x 139x 11x 13x 13x 10x 10x 13x 11x 139x 1x 1x 139x 5x 5x 4x 4x 5x 139x 1x 1x 1x 1x 1x 139x 1x 1x 1x 139x 281x 281x 281x 11462x 11462x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x 2x 11462x | 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;
}
}
|