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 120 121 122 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 22696x 22696x 22696x 22696x 22696x 22696x 22696x 22696x 22696x 22696x 1x 1x 1x 1x 1x 1x 11353x 11353x 11353x 11353x 11353x 33895x 33895x 33895x 33895x 33895x 33895x 33895x 33895x 33895x 33895x 11353x 11353x 31x 31x 26x 26x 31x 5x 5x 31x 31x 31x 11353x 11353x 10843x 10843x 11353x 11353x 246x 246x 11353x 11353x 252x 252x 11353x 11353x 321x 321x 321x 321x 1x 1x 320x 320x 320x 320x 320x 321x 318x 318x 318x 320x 320x 320x 11353x 11353x 11353x 11353x 638x 638x 638x 66x 66x 2x 2x 64x 66x 27x 1x 1x 26x 26x 26x 26x 66x 5x 5x 5x 5x 66x 638x 638x 638x 11353x 11353x 27x 27x 27x 11353x 11353x | import {Issue} from "../issue";
import {IObject} from "../objects/_iobject";
import {IRegistry} from "../_iregistry";
import * as Objects from "../objects";
import {IMethodLengthResult, MethodLengthStats} from "../utils/method_length_stats";
import {IRule, IRuleMetadata, RuleTag} from "./_irule";
import {BasicRuleConfig} from "./_basic_rule_config";
import {FormLengthStats} from "../utils/form_length_stats";
export class MethodLengthConf extends BasicRuleConfig {
/** Maximum method/form length in statements. */
public statements: number = 100;
/** Checks for empty methods/forms. */
public errorWhenEmpty: boolean = true;
/** Option to ignore test classes for this check. */
public ignoreTestClasses: boolean = false;
/** Option to check forms. */
public checkForms: boolean = true;
}
enum IssueType {
EmptyMethod,
MaxStatements,
}
export class MethodLength implements IRule {
private conf = new MethodLengthConf();
public getMetadata(): IRuleMetadata {
return {
key: "method_length",
title: "Method/Form Length",
shortDescription: `Checks relating to method/form length.`,
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#keep-methods-small
Abstract methods without statements are considered okay.`,
tags: [RuleTag.Styleguide, RuleTag.SingleFile],
};
}
private getDescription(issueType: IssueType, actual: string, type: string): string {
switch (issueType) {
case IssueType.EmptyMethod: {
return "Empty " + type;
}
case IssueType.MaxStatements: {
return "Reduce " + type + " length to max " + this.conf.statements + " statements, currently " + actual;
}
default: {
return "";
}
}
}
public getConfig() {
return this.conf;
}
public setConfig(conf: MethodLengthConf) {
this.conf = conf;
}
public initialize(_reg: IRegistry) {
return this;
}
public run(obj: IObject): Issue[] {
if (this.conf.ignoreTestClasses === true
&& obj instanceof Objects.Class
&& obj.getClassDefinition()?.isForTesting === true) {
return [];
}
const methodStats = MethodLengthStats.run(obj);
const methodIssues = this.check(methodStats, "METHOD");
let formIssues: Issue[] = [];
if (this.conf.checkForms) {
const formStats = FormLengthStats.run(obj);
formIssues = this.check(formStats, "FORM");
}
return methodIssues.concat(formIssues);
}
// ***********************
private check(stats: IMethodLengthResult[], type: string) {
const issues: Issue[] = [];
for (const s of stats) {
if ((this.conf.ignoreTestClasses === true)
&& s.file.getFilename().includes(".testclasses.")) {
continue;
}
if (s.count === 0 && this.conf.errorWhenEmpty === true) {
if (this.isAbstract(s)) {
continue;
}
const issue = Issue.atPosition(s.file, s.pos, this.getDescription(IssueType.EmptyMethod, "0", type), this.getMetadata().key, this.conf.severity);
issues.push(issue);
continue;
}
if (s.count > this.conf.statements) {
const message = this.getDescription(IssueType.MaxStatements, s.count.toString(), type);
const issue = Issue.atPosition(s.file, s.pos, message, this.getMetadata().key, this.conf.severity);
issues.push(issue);
}
}
return issues;
}
private isAbstract(result: IMethodLengthResult): boolean {
const cdef = result.file.getInfo().getClassDefinitionByName(result.className);
return cdef?.isAbstract === true;
}
} |