@abaplint/core 2.120.45 → 2.120.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/src/registry.js
CHANGED
|
@@ -17,7 +17,7 @@ class AllowedObjectNaming {
|
|
|
17
17
|
key: "allowed_object_naming",
|
|
18
18
|
title: "Allowed object naming",
|
|
19
19
|
shortDescription: `Enforces basic name length and namespace restrictions, see note SAP 104010`,
|
|
20
|
-
tags: [_irule_1.RuleTag.Naming, _irule_1.RuleTag.SingleFile],
|
|
20
|
+
tags: [_irule_1.RuleTag.Naming, _irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Syntax],
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
initialize(_reg) {
|
|
@@ -409,6 +409,10 @@ Make sure to test the downported code, it might not always be completely correct
|
|
|
409
409
|
if (found) {
|
|
410
410
|
return found;
|
|
411
411
|
}
|
|
412
|
+
found = this.outlineTableExpressionKeyBuiltin(low, high, lowFile, highSyntax);
|
|
413
|
+
if (found) {
|
|
414
|
+
return found;
|
|
415
|
+
}
|
|
412
416
|
found = this.assignWithTable(low, high, lowFile);
|
|
413
417
|
if (found) {
|
|
414
418
|
return found;
|
|
@@ -1106,6 +1110,69 @@ ${indentation}`);
|
|
|
1106
1110
|
}
|
|
1107
1111
|
return condition;
|
|
1108
1112
|
}
|
|
1113
|
+
/** A built-in function is only recognized as one in an operand position that admits an
|
|
1114
|
+
* expression, and "WITH KEY comp = ..." does not become such a position until v740. The
|
|
1115
|
+
* table expression rewrites carry the key operand over verbatim, so
|
|
1116
|
+
* "tab[ comp = to_upper( x ) ]" downports to a READ TABLE that a 702 or 731 compiler can
|
|
1117
|
+
* only read as a functional method call - "method TO_UPPER is unknown", reported as a
|
|
1118
|
+
* SYNTAX_ERROR of the whole class pool. Hoist the call into a variable first, an
|
|
1119
|
+
* assignment IS an expression position at 702.
|
|
1120
|
+
*
|
|
1121
|
+
* Built-ins that predate 702 (lines, strlen, numofchar, ...) carry no release in
|
|
1122
|
+
* BuiltIn.methods; they are accepted in the operand as they are and stay untouched. So do
|
|
1123
|
+
* functional method calls, which are exactly the reading that makes the built-in fail, and
|
|
1124
|
+
* the INDEX operand of "tab[ 1 ]", which is not a key operand. */
|
|
1125
|
+
outlineTableExpressionKeyBuiltin(low, high, lowFile, highSyntax) {
|
|
1126
|
+
if (!(low.get() instanceof _statement_1.Unknown)) {
|
|
1127
|
+
return undefined;
|
|
1128
|
+
}
|
|
1129
|
+
for (const tableExpression of high.findAllExpressionsRecursive(Expressions.TableExpression)) {
|
|
1130
|
+
let afterComponent = false;
|
|
1131
|
+
for (const child of tableExpression.getChildren()) {
|
|
1132
|
+
if (child.get() instanceof Expressions.ComponentChainSimple) {
|
|
1133
|
+
afterComponent = true;
|
|
1134
|
+
continue;
|
|
1135
|
+
}
|
|
1136
|
+
else if (afterComponent === false
|
|
1137
|
+
|| !(child.get() instanceof Expressions.Source)
|
|
1138
|
+
|| !(child instanceof nodes_1.ExpressionNode)) {
|
|
1139
|
+
continue;
|
|
1140
|
+
}
|
|
1141
|
+
const type = this.builtinReturnType(child, lowFile, highSyntax);
|
|
1142
|
+
if (type === undefined) {
|
|
1143
|
+
continue;
|
|
1144
|
+
}
|
|
1145
|
+
const uniqueName = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
|
|
1146
|
+
const indentation = " ".repeat(high.getFirstToken().getStart().getCol() - 1);
|
|
1147
|
+
const code = `DATA ${uniqueName} TYPE ${type}.\n` +
|
|
1148
|
+
indentation + `${uniqueName} = ${child.concatTokens()}.\n` +
|
|
1149
|
+
indentation;
|
|
1150
|
+
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getFirstToken().getStart(), code);
|
|
1151
|
+
const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, child.getFirstToken().getStart(), child.getLastToken().getEnd(), uniqueName);
|
|
1152
|
+
const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
|
|
1153
|
+
return issue_1.Issue.atToken(lowFile, child.getFirstToken(), "Outline built-in function in table expression key", this.getMetadata().key, this.conf.severity, fix);
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
return undefined;
|
|
1157
|
+
}
|
|
1158
|
+
/** the ABAP type returned by the built-in function this Source starts with, or undefined
|
|
1159
|
+
* if it does not start with one, or with one that predates 702 */
|
|
1160
|
+
builtinReturnType(source, lowFile, highSyntax) {
|
|
1161
|
+
var _a, _b, _c;
|
|
1162
|
+
const spag = highSyntax.spaghetti.lookupPosition(source.getFirstToken().getStart(), lowFile.getFilename());
|
|
1163
|
+
for (const r of (spag === null || spag === void 0 ? void 0 : spag.getData().references) || []) {
|
|
1164
|
+
if (r.referenceType !== _reference_1.ReferenceType.BuiltinMethodReference
|
|
1165
|
+
|| r.position.getStart().equals(source.getFirstToken().getStart()) === false) {
|
|
1166
|
+
continue;
|
|
1167
|
+
}
|
|
1168
|
+
const name = r.position.getName().toUpperCase();
|
|
1169
|
+
if (((_a = _builtin_1.BuiltIn.methods[name]) === null || _a === void 0 ? void 0 : _a.release) === undefined) {
|
|
1170
|
+
return undefined;
|
|
1171
|
+
}
|
|
1172
|
+
return (_c = (_b = _builtin_1.BuiltIn.searchBuiltin(name)) === null || _b === void 0 ? void 0 : _b.getParameters().getReturning()) === null || _c === void 0 ? void 0 : _c.getType().toABAP();
|
|
1173
|
+
}
|
|
1174
|
+
return undefined;
|
|
1175
|
+
}
|
|
1109
1176
|
outlineCatchSimple(node, lowFile) {
|
|
1110
1177
|
// outlines "CATCH cx_bcs INTO DATA(lx_bcs_excep).", note that this does not need to look at types
|
|
1111
1178
|
var _a, _b;
|
|
@@ -2716,9 +2783,13 @@ ${indentation} output = ${uniqueName}.\n`;
|
|
|
2716
2783
|
continue;
|
|
2717
2784
|
}
|
|
2718
2785
|
const uniqueName = this.uniqueName(i.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
|
|
2719
|
-
const type = this.findType(i, lowFile, highSyntax);
|
|
2720
2786
|
const indent = " ".repeat(high.getFirstToken().getStart().getCol() - 1);
|
|
2721
|
-
|
|
2787
|
+
// the CONV type might just be a component of the row type, so prefer the row type
|
|
2788
|
+
const rowOf = this.findRowTypeOf(high, i);
|
|
2789
|
+
const declaration = rowOf === undefined
|
|
2790
|
+
? `DATA ${uniqueName} TYPE ${this.findType(i, lowFile, highSyntax)}.`
|
|
2791
|
+
: `DATA ${uniqueName} LIKE LINE OF ${rowOf}.`;
|
|
2792
|
+
const abap = declaration + "\n" +
|
|
2722
2793
|
indent + `${uniqueName} = ${body}.\n` +
|
|
2723
2794
|
indent;
|
|
2724
2795
|
const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getFirstToken().getStart(), abap);
|
|
@@ -2728,6 +2799,19 @@ ${indentation} output = ${uniqueName}.\n`;
|
|
|
2728
2799
|
}
|
|
2729
2800
|
return undefined;
|
|
2730
2801
|
}
|
|
2802
|
+
/** if the source expression is the complete source of an INSERT or APPEND statement, then the
|
|
2803
|
+
* outlined variable must be typed via the row type of the table, returns the table name */
|
|
2804
|
+
findRowTypeOf(high, source) {
|
|
2805
|
+
var _a;
|
|
2806
|
+
if (!(high.get() instanceof Statements.InsertInternal)
|
|
2807
|
+
&& !(high.get() instanceof Statements.Append)) {
|
|
2808
|
+
return undefined;
|
|
2809
|
+
}
|
|
2810
|
+
else if (high.getChildren()[1] !== source) {
|
|
2811
|
+
return undefined;
|
|
2812
|
+
}
|
|
2813
|
+
return (_a = high.findDirectExpression(Expressions.Target)) === null || _a === void 0 ? void 0 : _a.concatTokens();
|
|
2814
|
+
}
|
|
2731
2815
|
// "CAST" to "?="
|
|
2732
2816
|
outlineCast(low, high, lowFile, highSyntax) {
|
|
2733
2817
|
var _a;
|