@abaplint/core
Version:
abaplint - Core API
375 lines (367 loc) • 14.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AlignParameters = exports.AlignParametersConf = void 0;
const issue_1 = require("../issue");
const Expressions = require("../abap/2_statements/expressions");
const _abap_rule_1 = require("./_abap_rule");
const _basic_rule_config_1 = require("./_basic_rule_config");
const _irule_1 = require("./_irule");
const position_1 = require("../position");
const Statements = require("../abap/2_statements/statements");
const edit_helper_1 = require("../edit_helper");
class AlignParametersConf extends _basic_rule_config_1.BasicRuleConfig {
}
exports.AlignParametersConf = AlignParametersConf;
class AlignParameters extends _abap_rule_1.ABAPRule {
constructor() {
super(...arguments);
this.conf = new AlignParametersConf();
}
getMetadata() {
return {
key: "align_parameters",
title: "Align Parameters",
shortDescription: `Checks for vertially aligned parameters`,
extendedInformation: `Checks:
* function module calls
* method calls
* VALUE constructors
* NEW constructors
* RAISE EXCEPTION statements
* CREATE OBJECT statements
* RAISE EVENT statements
https://github.com/SAP/styleguides/blob/master/clean-abap/CleanABAP.md#align-parameters
Does not take effect on non functional method calls, use https://rules.abaplint.org/functional_writing/
If parameters are on the same row, no issues are reported, see
https://rules.abaplint.org/max_one_method_parameter_per_line/ for splitting parameters to lines`,
tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Whitespace, _irule_1.RuleTag.Styleguide, _irule_1.RuleTag.Quickfix],
badExample: `CALL FUNCTION 'FOOBAR'
EXPORTING
foo = 2
parameter = 3.
foobar( moo = 1
param = 1 ).
foo = VALUE #(
foo = bar
moo = 2 ).`,
goodExample: `CALL FUNCTION 'FOOBAR'
EXPORTING
foo = 2
parameter = 3.
foobar( moo = 1
param = 1 ).
foo = VALUE #(
foo = bar
moo = 2 ).
DATA(sdf) = VALUE type(
common_val = 2
another_common = 5
( row_value = 4
value_foo = 5 ) ).`,
};
}
getConfig() {
return this.conf;
}
setConfig(conf) {
this.conf = conf;
}
runParsed(file) {
const issues = [];
const stru = file.getStructure();
if (stru === undefined) {
return issues; // parser error
}
const candidates = [];
candidates.push(...this.functionParameterCandidates(stru));
candidates.push(...this.methodCallParamCandidates(stru));
candidates.push(...this.valueBodyCandidates(stru));
candidates.push(...this.raiseAndCreateCandidates(stru));
candidates.push(...this.newCandidates(stru));
for (const c of candidates) {
const i = this.checkCandidate(c, file);
if (i) {
issues.push(i);
}
}
return issues;
}
checkCandidate(candidate, file) {
if (candidate.parameters.length === 0) {
return undefined;
}
let expectedEqualsColumn = 0;
let row = 0;
for (const p of candidate.parameters) {
const currentCol = p.left.getLastToken().getCol() + p.left.getLastToken().getStr().length + 1;
if (p.eq.getRow() === row) {
return undefined;
}
row = p.eq.getRow();
if (currentCol > expectedEqualsColumn) {
expectedEqualsColumn = currentCol;
}
}
for (const p of candidate.parameters) {
if (p.eq.getCol() !== expectedEqualsColumn) {
let fix;
if (p.eq.getCol() < expectedEqualsColumn) {
fix = edit_helper_1.EditHelper.insertAt(file, p.eq, " ".repeat(expectedEqualsColumn - p.eq.getCol()));
}
else {
fix = edit_helper_1.EditHelper.deleteRange(file, new position_1.Position(p.eq.getRow(), expectedEqualsColumn), p.eq);
}
const message = "Align parameters to column " + expectedEqualsColumn;
return issue_1.Issue.atPosition(file, p.eq, message, this.getMetadata().key, this.getConfig().severity, fix);
}
}
return undefined;
}
newCandidates(stru) {
const candidates = [];
for (const vb of stru.findAllExpressionsRecursive(Expressions.NewObject)) {
const parameters = [];
const fieldAssignments = vb.findDirectExpressions(Expressions.FieldAssignment);
if (fieldAssignments.length >= 2) {
for (const fs of fieldAssignments) {
const children = fs.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
if (parameters.length > 0) {
candidates.push({ parameters });
continue;
}
}
const list = vb.findDirectExpression(Expressions.ParameterListS);
if (list) {
for (const c of list.getChildren()) {
const children = c.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
if (parameters.length > 0) {
candidates.push({ parameters });
}
}
}
return candidates;
}
valueBodyCandidates(stru) {
const candidates = [];
for (const vb of stru.findAllExpressionsRecursive(Expressions.ValueBody)) {
const parameters = [];
const fieldAssignments = vb.findDirectExpressions(Expressions.FieldAssignment);
if (fieldAssignments.length <= 1) {
continue;
}
for (const fs of fieldAssignments) {
const children = fs.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
if (parameters.length > 0) {
candidates.push({ parameters });
}
}
for (const vb of stru.findAllExpressionsRecursive(Expressions.ValueBodyLine)) {
const parameters = [];
const fieldAssignments = vb.findDirectExpressions(Expressions.FieldAssignment);
if (fieldAssignments.length <= 1) {
continue;
}
for (const fs of fieldAssignments) {
const children = fs.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
if (parameters.length > 0) {
candidates.push({ parameters });
}
}
return candidates;
}
raiseAndCreateCandidates(stru) {
const candidates = [];
const statements = stru.findAllStatements(Statements.Raise);
statements.push(...stru.findAllStatements(Statements.CreateObject));
statements.push(...stru.findAllStatements(Statements.RaiseEvent));
for (const raise of statements) {
const parameters = [];
const param = raise.findDirectExpression(Expressions.ParameterListS);
for (const p of (param === null || param === void 0 ? void 0 : param.getChildren()) || []) {
const children = p.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
const ex = raise.findDirectExpression(Expressions.ParameterListExceptions);
for (const e of (ex === null || ex === void 0 ? void 0 : ex.getChildren()) || []) {
const children = e.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
if (parameters.length > 0) {
candidates.push({ parameters });
}
}
return candidates;
}
methodCallParamCandidates(stru) {
var _a, _b, _c;
const candidates = [];
for (const mcp of stru.findAllExpressionsRecursive(Expressions.MethodCallParam)) {
const parameters = [];
for (const param of ((_a = mcp.findDirectExpression(Expressions.ParameterListS)) === null || _a === void 0 ? void 0 : _a.getChildren()) || []) {
const children = param.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
const mp = mcp.findDirectExpression(Expressions.MethodParameters);
if (mp) {
for (const p of ((_b = mp.findDirectExpression(Expressions.ParameterListS)) === null || _b === void 0 ? void 0 : _b.getChildren()) || []) {
const children = p.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
for (const l of mp.findDirectExpressions(Expressions.ParameterListT)) {
for (const p of l.findDirectExpressions(Expressions.ParameterT) || []) {
const children = p.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
}
const rec = mp.findDirectExpression(Expressions.ParameterT);
if (rec) {
const children = rec.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
for (const ex of ((_c = mp.findDirectExpression(Expressions.ParameterListExceptions)) === null || _c === void 0 ? void 0 : _c.getChildren()) || []) {
const children = ex.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
}
if (parameters.length > 0) {
candidates.push({ parameters });
}
}
return candidates;
}
functionParameterCandidates(stru) {
const candidates = [];
for (const fp of stru.findAllExpressionsRecursive(Expressions.FunctionParameters)) {
const parameters = [];
for (const p of fp.findAllExpressions(Expressions.FunctionExportingParameter)) {
const children = p.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
for (const list of fp.findDirectExpressions(Expressions.ParameterListT)) {
for (const pt of list.findDirectExpressions(Expressions.ParameterT)) {
const children = pt.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
}
const list = fp.findDirectExpression(Expressions.ParameterListExceptions);
if (list) {
for (const pt of list.findDirectExpressions(Expressions.ParameterException)) {
const children = pt.getChildren();
if (children.length < 3) {
continue; // unexpected
}
parameters.push({
left: children[0],
eq: children[1].getFirstToken().getStart(),
right: children[2],
});
}
}
if (parameters.length > 0) {
candidates.push({ parameters });
}
}
return candidates;
}
}
exports.AlignParameters = AlignParameters;
//# sourceMappingURL=align_parameters.js.map