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 11722x 11722x 11722x 11722x 11722x 34998x 34998x 34998x 34998x 34998x 34998x 34998x 11722x 11722x 1x 1x 11722x 11722x 11175x 11175x 11722x 11722x 253x 253x 11722x 11722x 286x 286x 286x 144x 144x 128x 128x 16x 144x 5x 5x 16x 144x 11x 13x 13x 10x 10x 13x 11x 144x 1x 1x 144x 5x 5x 4x 4x 5x 144x 1x 1x 1x 1x 1x 144x 1x 1x 1x 144x 286x 286x 286x 11722x 11722x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x 2x 11722x | 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;
}
}
|