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 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 23502x 23502x 23502x 23502x 1x 11752x 11752x 11752x 11752x 11752x 11752x 11752x 35119x 35119x 35119x 35119x 35119x 35119x 35119x 35119x 35119x 35119x 35119x 11752x 11752x 20x 20x 11752x 11752x 11241x 11241x 11752x 11752x 240x 240x 11752x 11752x 285x 285x 285x 285x 285x 12x 12x 273x 273x 285x 39x 39x 39x 20x 20x 39x 273x 273x 273x 11752x 11752x 285x 216x 216x 216x 216x 216x 216x 216x 216x 216x 216x 216x 216x 216x 216x 216x 285x 11752x 11752x 20x 20x 20x 20x 19x 19x 19x 20x 1x 1x 1x 20x 11752x 11752x | import * as Expressions from "../abap/2_statements/expressions";
import {Issue} from "../issue";
import {ABAPRule} from "./_abap_rule";
import {BasicRuleConfig} from "./_basic_rule_config";
import {EditHelper} from "../edit_helper";
import {AbstractToken} from "../abap/1_lexer/tokens/abstract_token";
import {IRuleMetadata, RuleTag} from "./_irule";
import {ABAPFile} from "../abap/abap_file";
export class PreferredCompareOperatorConf extends BasicRuleConfig {
/** Operators which are not allowed */
public badOperators: string[] = ["EQ", "><", "NE", "GE", "GT", "LT", "LE"];
}
export class PreferredCompareOperator extends ABAPRule {
private conf = new PreferredCompareOperatorConf();
private readonly operatorMapping: Map<string, string> = new Map<string, string>();
public getMetadata(): IRuleMetadata {
return {
key: "preferred_compare_operator",
title: "Preferred compare operator",
shortDescription: `Configure undesired operator variants`,
tags: [RuleTag.SingleFile, RuleTag.Quickfix],
badExample: `IF foo EQ bar.
ENDIF.`,
goodExample: `IF foo = bar.
ENDIF.`,
};
}
private getDescription(operator: string): string {
return "Compare operator \"" + operator + "\" not preferred";
}
public getConfig() {
return this.conf;
}
public setConfig(conf: PreferredCompareOperatorConf) {
this.conf = conf;
}
public runParsed(file: ABAPFile) {
this.buildMapping();
const issues: Issue[] = [];
const struc = file.getStructure();
if (struc === undefined) {
return [];
}
const operators = struc.findAllExpressionsMulti([Expressions.CompareOperator, Expressions.SQLCompareOperator]);
for (const op of operators) {
const token = op.getLastToken();
// todo, performance, lookup in hash map instead(JS object)
if (this.conf.badOperators.indexOf(token.getStr().toUpperCase()) >= 0) {
issues.push(this.createIssue(token, file));
}
}
return issues;
}
private buildMapping() {
if (this.operatorMapping.size === 0) {
this.operatorMapping.set("EQ", "=");
this.operatorMapping.set("><", "<>");
this.operatorMapping.set("NE", "<>");
this.operatorMapping.set("GE", ">=");
this.operatorMapping.set("GT", ">");
this.operatorMapping.set("LT", "<");
this.operatorMapping.set("LE", "<=");
this.operatorMapping.set("=", "EQ");
this.operatorMapping.set("<>", "NE");
this.operatorMapping.set(">=", "GE");
this.operatorMapping.set(">", "GT");
this.operatorMapping.set("<", "LT");
this.operatorMapping.set("<=", "LE");
}
}
private createIssue(token: AbstractToken, file: ABAPFile): Issue {
const message = this.getDescription(token.getStr());
const replacementToken = this.operatorMapping?.get(token.getStr());
// values in badOperators can be entered by the user and may not necessarily be actual operators
if (replacementToken) {
const fix = EditHelper.replaceRange(file, token.getStart(), token.getEnd(), replacementToken);
const issue = Issue.atToken(file, token, message, this.getMetadata().key, this.conf.severity, fix);
return issue;
} else {
const issue = Issue.atToken(file, token, message, this.getMetadata().key, this.conf.severity);
return issue;
}
}
} |