@abaplint/core 2.120.74 → 2.120.76
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/abaplint.d.ts +5 -1
- package/build/src/abap/2_statements/combi.js +143 -51
- package/build/src/abap/5_syntax/_builtin.js +8 -0
- package/build/src/abap/5_syntax/_loop_table_change.js +126 -0
- package/build/src/abap/5_syntax/expressions/_substring.js +83 -0
- package/build/src/abap/5_syntax/expressions/attribute_chain.js +3 -16
- package/build/src/abap/5_syntax/expressions/compare.js +33 -8
- package/build/src/abap/5_syntax/expressions/field_chain.js +5 -14
- package/build/src/abap/5_syntax/expressions/method_call_chain.js +16 -1
- package/build/src/abap/5_syntax/expressions/method_call_param.js +3 -0
- package/build/src/abap/5_syntax/expressions/target.js +14 -2
- package/build/src/abap/5_syntax/statements/append.js +6 -0
- package/build/src/abap/5_syntax/statements/read_table.js +39 -0
- package/build/src/abap/5_syntax/structures/cleanup.js +105 -0
- package/build/src/abap/5_syntax/syntax.js +13 -0
- package/build/src/ddic.js +1 -1
- package/build/src/objects/domain.js +4 -1
- package/build/src/registry.js +1 -1
- package/build/src/rules/abapdoc_html_tag.js +123 -0
- package/build/src/rules/abapdoc_leading_at.js +117 -0
- package/build/src/rules/abapdoc_parameter_names.js +149 -0
- package/build/src/rules/cds_check_syntax.js +4 -4
- package/build/src/rules/change_if_to_case.js +3 -2
- package/build/src/rules/changing_sorted_line.js +235 -0
- package/build/src/rules/class_attribute_names.js +15 -6
- package/build/src/rules/delete_index_in_loop.js +163 -0
- package/build/src/rules/final_newline.js +78 -0
- package/build/src/rules/forbidden_identifier.js +4 -3
- package/build/src/rules/forbidden_void_type.js +4 -9
- package/build/src/rules/index.js +11 -0
- package/build/src/rules/inline_packed_computation.js +220 -0
- package/build/src/rules/intf_referencing_clas.js +3 -1
- package/build/src/rules/line_only_punc.js +1 -1
- package/build/src/rules/local_class_naming.js +15 -2
- package/build/src/rules/local_variable_names.js +18 -9
- package/build/src/rules/macro_naming.js +3 -2
- package/build/src/rules/method_parameter_names.js +17 -7
- package/build/src/rules/modify_only_own_db_tables.js +3 -2
- package/build/src/rules/no_prefixes.js +25 -12
- package/build/src/rules/object_naming.js +18 -3
- package/build/src/rules/prefer_inline_cast.js +276 -0
- package/build/src/rules/range_row_values.js +200 -0
- package/build/src/rules/redundant_conversion.js +3 -0
- package/build/src/rules/selection_screen_naming.js +21 -2
- package/build/src/rules/sicf_consistency.js +1 -2
- package/build/src/rules/sort_empty_key.js +188 -0
- package/build/src/rules/subrc_after_assign.js +220 -0
- package/build/src/rules/types_naming.js +3 -2
- package/build/src/rules/use_message_class.js +64 -1
- package/build/src/rules/wrong_abapdoc_position.js +58 -11
- package/build/src/rules/xml_consistency.js +6 -2
- package/build/src/utils/name_validator.js +7 -3
- package/package.json +1 -1
|
@@ -63,6 +63,11 @@ class Compare {
|
|
|
63
63
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), initialMessage));
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
|
+
const predicateMessage = this.checkPredicateOperand(sources, input);
|
|
67
|
+
if (predicateMessage !== undefined) {
|
|
68
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), predicateMessage));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
66
71
|
const typeUtils = new _type_utils_1.TypeUtils(input.scope);
|
|
67
72
|
const compareOperator = (_a = node.findDirectExpression(Expressions.CompareOperator)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase();
|
|
68
73
|
if (compareOperator === "CS"
|
|
@@ -103,6 +108,31 @@ class Compare {
|
|
|
103
108
|
if ((chain === null || chain === void 0 ? void 0 : chain.length) === 4 && chain[0] instanceof nodes_1.TokenNode && (first === "XSDBOOL" || first === "BOOLC")) {
|
|
104
109
|
return `Built-in function "${chain[0].getFirstToken().getStr()}" cannot be the operand of IS INITIAL`;
|
|
105
110
|
}
|
|
111
|
+
const name = this.builtinCallName(node.findDirectExpression(Expressions.Source), input);
|
|
112
|
+
const returning = (_d = (_c = _builtin_1.BuiltIn.searchBuiltin(name)) === null || _c === void 0 ? void 0 : _c.getParameters().getReturning()) === null || _d === void 0 ? void 0 : _d.getType();
|
|
113
|
+
if (returning instanceof basic_1.StringType || returning instanceof basic_1.CharacterType) {
|
|
114
|
+
return `Built-in function "${name}" cannot be the operand of IS INITIAL`;
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
// a predicate function, contains( ) or line_exists( ), is a relational expression and not a value,
|
|
119
|
+
// it can stand alone as a condition or inside boolc( ) or xsdbool( ), but cannot be an operand of a comparison
|
|
120
|
+
static checkPredicateOperand(sources, input) {
|
|
121
|
+
if (input.scope.getOpenABAP()) {
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
for (const source of sources) {
|
|
125
|
+
const name = this.builtinCallName(source, input);
|
|
126
|
+
if (_builtin_1.BuiltIn.isPredicate(name) === true) {
|
|
127
|
+
return `Predicate function "${name}" cannot be the operand of a comparison`;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
// the name of the built-in function when the source is exactly one call of it, not hidden by a method of the same name
|
|
133
|
+
static builtinCallName(source, input) {
|
|
134
|
+
var _a;
|
|
135
|
+
const chain = source === null || source === void 0 ? void 0 : source.getChildren();
|
|
106
136
|
if ((chain === null || chain === void 0 ? void 0 : chain.length) !== 1 || !(chain[0] instanceof nodes_1.ExpressionNode) || !(chain[0].get() instanceof Expressions.MethodCallChain)) {
|
|
107
137
|
return undefined;
|
|
108
138
|
}
|
|
@@ -110,9 +140,8 @@ class Compare {
|
|
|
110
140
|
if (calls.length !== 1 || !(calls[0] instanceof nodes_1.ExpressionNode) || !(calls[0].get() instanceof Expressions.MethodCall)) {
|
|
111
141
|
return undefined;
|
|
112
142
|
}
|
|
113
|
-
const name = (
|
|
114
|
-
|
|
115
|
-
if (name === undefined || builtin === undefined) {
|
|
143
|
+
const name = (_a = calls[0].findDirectExpression(Expressions.MethodName)) === null || _a === void 0 ? void 0 : _a.concatTokens();
|
|
144
|
+
if (name === undefined || _builtin_1.BuiltIn.searchBuiltin(name) === undefined) {
|
|
116
145
|
return undefined;
|
|
117
146
|
}
|
|
118
147
|
// a method of the same name hides the built-in function
|
|
@@ -120,11 +149,7 @@ class Compare {
|
|
|
120
149
|
if (enclosing !== undefined && new _object_oriented_1.ObjectOriented(input.scope).searchMethodName(enclosing, name).method !== undefined) {
|
|
121
150
|
return undefined;
|
|
122
151
|
}
|
|
123
|
-
|
|
124
|
-
if (returning instanceof basic_1.StringType || returning instanceof basic_1.CharacterType) {
|
|
125
|
-
return `Built-in function "${name}" cannot be the operand of IS INITIAL`;
|
|
126
|
-
}
|
|
127
|
-
return undefined;
|
|
152
|
+
return name;
|
|
128
153
|
}
|
|
129
154
|
}
|
|
130
155
|
exports.Compare = Compare;
|
|
@@ -48,6 +48,7 @@ const expressions_1 = require("../../2_statements/expressions");
|
|
|
48
48
|
const dereference_1 = require("./dereference");
|
|
49
49
|
const source_field_symbol_1 = require("./source_field_symbol");
|
|
50
50
|
const source_field_1 = require("./source_field");
|
|
51
|
+
const _substring_1 = require("./_substring");
|
|
51
52
|
const _syntax_input_1 = require("../_syntax_input");
|
|
52
53
|
const version_1 = require("../../../version");
|
|
53
54
|
class FieldChain {
|
|
@@ -160,24 +161,14 @@ class FieldChain {
|
|
|
160
161
|
}
|
|
161
162
|
else if (current.get() instanceof Expressions.FieldOffset && current instanceof nodes_1.ExpressionNode) {
|
|
162
163
|
const offset = field_offset_1.FieldOffset.runSyntax(current, input);
|
|
163
|
-
if (
|
|
164
|
-
|
|
165
|
-
context = new basic_1.CharacterType(context.getLength() - offset);
|
|
166
|
-
}
|
|
167
|
-
else if (context instanceof basic_1.HexType) {
|
|
168
|
-
context = new basic_1.HexType(context.getLength() - offset);
|
|
169
|
-
}
|
|
164
|
+
if (!(0, _substring_1.isFieldSymbolItself)(children, i)) {
|
|
165
|
+
context = (0, _substring_1.substringType)(context, offset, undefined, current, input);
|
|
170
166
|
}
|
|
171
167
|
}
|
|
172
168
|
else if (current.get() instanceof Expressions.FieldLength && current instanceof nodes_1.ExpressionNode) {
|
|
173
169
|
const length = field_length_1.FieldLength.runSyntax(current, input);
|
|
174
|
-
if (
|
|
175
|
-
|
|
176
|
-
context = new basic_1.CharacterType(length);
|
|
177
|
-
}
|
|
178
|
-
else if (context instanceof basic_1.HexType) {
|
|
179
|
-
context = new basic_1.HexType(length);
|
|
180
|
-
}
|
|
170
|
+
if (!(0, _substring_1.isFieldSymbolItself)(children, i)) {
|
|
171
|
+
context = (0, _substring_1.substringType)(context, undefined, length, current, input);
|
|
181
172
|
}
|
|
182
173
|
}
|
|
183
174
|
prev = current.concatTokens();
|
|
@@ -141,7 +141,12 @@ class MethodCallChain {
|
|
|
141
141
|
}
|
|
142
142
|
const param = current.findDirectExpression(Expressions.MethodCallParam);
|
|
143
143
|
if (param && method) {
|
|
144
|
-
method_call_param_1.MethodCallParam.runSyntax(param, input, method);
|
|
144
|
+
const argumentType = method_call_param_1.MethodCallParam.runSyntax(param, input, method);
|
|
145
|
+
if (method instanceof _builtin_1.BuiltInMethod
|
|
146
|
+
&& _builtin_1.BuiltIn.returnsArgumentType(methodName)
|
|
147
|
+
&& this.isNumeric(argumentType)) {
|
|
148
|
+
context = argumentType;
|
|
149
|
+
}
|
|
145
150
|
}
|
|
146
151
|
else if (param && context instanceof basic_1.VoidType) {
|
|
147
152
|
method_call_param_1.MethodCallParam.runSyntax(param, input, context);
|
|
@@ -158,6 +163,16 @@ class MethodCallChain {
|
|
|
158
163
|
return context;
|
|
159
164
|
}
|
|
160
165
|
//////////////////////////////////////
|
|
166
|
+
static isNumeric(type) {
|
|
167
|
+
return type instanceof basic_1.IntegerType
|
|
168
|
+
|| type instanceof basic_1.Integer8Type
|
|
169
|
+
|| type instanceof basic_1.PackedType
|
|
170
|
+
|| type instanceof basic_1.FloatType
|
|
171
|
+
|| type instanceof basic_1.FloatingPointType
|
|
172
|
+
|| type instanceof basic_1.DecFloatType
|
|
173
|
+
|| type instanceof basic_1.DecFloat16Type
|
|
174
|
+
|| type instanceof basic_1.DecFloat34Type;
|
|
175
|
+
}
|
|
161
176
|
static findTop(first, input, targetType) {
|
|
162
177
|
var _a;
|
|
163
178
|
if (first.get() instanceof Expressions.ClassName) {
|
|
@@ -46,6 +46,7 @@ const constant_1 = require("./constant");
|
|
|
46
46
|
const _check_offset_length_1 = require("./_check_offset_length");
|
|
47
47
|
const _check_text_symbol_1 = require("./_check_text_symbol");
|
|
48
48
|
class MethodCallParam {
|
|
49
|
+
/** returns the type of the unnamed argument, if any */
|
|
49
50
|
static runSyntax(node, input, method) {
|
|
50
51
|
if (!(node.get() instanceof Expressions.MethodCallParam)) {
|
|
51
52
|
const message = "MethodCallParam, unexpected input";
|
|
@@ -125,6 +126,7 @@ class MethodCallParam {
|
|
|
125
126
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
126
127
|
return;
|
|
127
128
|
}
|
|
129
|
+
return sourceType;
|
|
128
130
|
}
|
|
129
131
|
else if (child instanceof nodes_1.ExpressionNode && child.get() instanceof Expressions.ParameterListS) {
|
|
130
132
|
new method_parameters_1.MethodParameters().checkExporting(child, input, method);
|
|
@@ -137,6 +139,7 @@ class MethodCallParam {
|
|
|
137
139
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
138
140
|
return;
|
|
139
141
|
}
|
|
142
|
+
return undefined;
|
|
140
143
|
}
|
|
141
144
|
}
|
|
142
145
|
exports.MethodCallParam = MethodCallParam;
|
|
@@ -47,6 +47,7 @@ const table_expression_1 = require("./table_expression");
|
|
|
47
47
|
const expressions_1 = require("../../2_statements/expressions");
|
|
48
48
|
const field_length_1 = require("./field_length");
|
|
49
49
|
const cast_1 = require("./cast");
|
|
50
|
+
const _substring_1 = require("./_substring");
|
|
50
51
|
const _syntax_input_1 = require("../_syntax_input");
|
|
51
52
|
const version_1 = require("../../../version");
|
|
52
53
|
class Target {
|
|
@@ -154,6 +155,8 @@ class Target {
|
|
|
154
155
|
context = attribute_name_1.AttributeName.runSyntax(context, current, input, type);
|
|
155
156
|
}
|
|
156
157
|
}
|
|
158
|
+
// the substring is checked, but the type of the whole field is returned
|
|
159
|
+
let substring = context;
|
|
157
160
|
const offset = node.findDirectExpression(Expressions.FieldOffset);
|
|
158
161
|
if (offset) {
|
|
159
162
|
if (context instanceof basic_1.XStringType || context instanceof basic_1.StringType) {
|
|
@@ -161,7 +164,10 @@ class Target {
|
|
|
161
164
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
162
165
|
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
163
166
|
}
|
|
164
|
-
field_offset_1.FieldOffset.runSyntax(offset, input);
|
|
167
|
+
const value = field_offset_1.FieldOffset.runSyntax(offset, input);
|
|
168
|
+
if (!(0, _substring_1.isFieldSymbolItself)(children, children.indexOf(offset))) {
|
|
169
|
+
substring = (0, _substring_1.substringType)(substring, value, undefined, offset, input);
|
|
170
|
+
}
|
|
165
171
|
}
|
|
166
172
|
const length = node.findDirectExpression(Expressions.FieldLength);
|
|
167
173
|
if (length) {
|
|
@@ -170,7 +176,13 @@ class Target {
|
|
|
170
176
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
171
177
|
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
172
178
|
}
|
|
173
|
-
field_length_1.FieldLength.runSyntax(length, input);
|
|
179
|
+
const value = field_length_1.FieldLength.runSyntax(length, input);
|
|
180
|
+
if (!(0, _substring_1.isFieldSymbolItself)(children, children.indexOf(length))) {
|
|
181
|
+
substring = (0, _substring_1.substringType)(substring, undefined, value, length, input);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (substring instanceof basic_1.VoidType && !(context instanceof basic_1.VoidType)) {
|
|
185
|
+
return substring;
|
|
174
186
|
}
|
|
175
187
|
return context;
|
|
176
188
|
}
|
|
@@ -50,6 +50,12 @@ class Append {
|
|
|
50
50
|
if (target) {
|
|
51
51
|
targetType = target_1.Target.runSyntax(target, input);
|
|
52
52
|
}
|
|
53
|
+
// a hashed table has no index, APPEND adds at the end
|
|
54
|
+
if (targetType instanceof basic_1.TableType && targetType.getAccessType() === basic_1.TableAccessType.hashed) {
|
|
55
|
+
const message = "Implicit or explicit index operation on hashed table is not possible";
|
|
56
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
53
59
|
const fsTarget = node.findExpressionAfterToken("ASSIGNING");
|
|
54
60
|
if (fsTarget && fsTarget.get() instanceof Expressions.FSTarget) {
|
|
55
61
|
if (!(targetType instanceof basic_1.TableType) && !(targetType instanceof basic_1.VoidType) && !(targetType instanceof basic_1.UnknownType)) {
|
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.ReadTable = void 0;
|
|
37
37
|
const Expressions = __importStar(require("../../2_statements/expressions"));
|
|
38
|
+
const nodes_1 = require("../../nodes");
|
|
38
39
|
const basic_1 = require("../../types/basic");
|
|
39
40
|
const source_1 = require("../expressions/source");
|
|
40
41
|
const inline_data_1 = require("../expressions/inline_data");
|
|
@@ -43,6 +44,9 @@ const fstarget_1 = require("../expressions/fstarget");
|
|
|
43
44
|
const component_compare_simple_1 = require("../expressions/component_compare_simple");
|
|
44
45
|
const _type_utils_1 = require("../_type_utils");
|
|
45
46
|
const _syntax_input_1 = require("../_syntax_input");
|
|
47
|
+
const _builtin_1 = require("../_builtin");
|
|
48
|
+
const _object_oriented_1 = require("../_object_oriented");
|
|
49
|
+
const version_1 = require("../../../version");
|
|
46
50
|
class ReadTable {
|
|
47
51
|
runSyntax(node, input) {
|
|
48
52
|
const concat = node.concatTokens().toUpperCase();
|
|
@@ -69,6 +73,11 @@ class ReadTable {
|
|
|
69
73
|
const components = node.findDirectExpression(Expressions.ComponentCompareSimple);
|
|
70
74
|
if (components !== undefined) {
|
|
71
75
|
component_compare_simple_1.ComponentCompareSimple.runSyntax(components, input, rowType);
|
|
76
|
+
const keyMessage = this.checkKeyOperands(components, input);
|
|
77
|
+
if (keyMessage !== undefined) {
|
|
78
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), keyMessage));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
72
81
|
}
|
|
73
82
|
const indexSource = node.findExpressionAfterToken("INDEX");
|
|
74
83
|
if (indexSource) {
|
|
@@ -164,6 +173,36 @@ class ReadTable {
|
|
|
164
173
|
}
|
|
165
174
|
}
|
|
166
175
|
}
|
|
176
|
+
// before 7.40 a WITH [TABLE] KEY operand is not an expression position, a built-in function from 7.02 on
|
|
177
|
+
// is read as a functional method call there, "method TO_UPPER is unknown" on a system, while
|
|
178
|
+
// functional methods and the older built-in functions like lines( ) are accepted
|
|
179
|
+
checkKeyOperands(node, input) {
|
|
180
|
+
var _a, _b;
|
|
181
|
+
if (input.scope.getOpenABAP() || (0, version_1.releaseAtLeast)(input.scope.getRelease(), version_1.Release.v740sp02)) {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
for (const operand of node.findDirectExpressionsMulti([Expressions.Source, Expressions.SimpleSource4])) {
|
|
185
|
+
const chain = operand.getChildren();
|
|
186
|
+
if (chain.length !== 1 || !(chain[0] instanceof nodes_1.ExpressionNode) || !(chain[0].get() instanceof Expressions.MethodCallChain)) {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
const calls = chain[0].getChildren();
|
|
190
|
+
if (calls.length !== 1 || !(calls[0] instanceof nodes_1.ExpressionNode) || !(calls[0].get() instanceof Expressions.MethodCall)) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const name = (_a = calls[0].findDirectExpression(Expressions.MethodName)) === null || _a === void 0 ? void 0 : _a.concatTokens();
|
|
194
|
+
if (name === undefined || ((_b = _builtin_1.BuiltIn.methods[name.toUpperCase()]) === null || _b === void 0 ? void 0 : _b.release) === undefined) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
// a method of the same name hides the built-in function
|
|
198
|
+
const enclosing = input.scope.findClassDefinition(input.scope.getEnclosingClassName());
|
|
199
|
+
if (enclosing !== undefined && new _object_oriented_1.ObjectOriented(input.scope).searchMethodName(enclosing, name).method !== undefined) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
return `Built-in function "${name}" cannot be a READ TABLE key operand before 7.40`;
|
|
203
|
+
}
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
167
206
|
}
|
|
168
207
|
exports.ReadTable = ReadTable;
|
|
169
208
|
//# sourceMappingURL=read_table.js.map
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Cleanup = void 0;
|
|
37
|
+
const Statements = __importStar(require("../../2_statements/statements"));
|
|
38
|
+
const Structures = __importStar(require("../../3_structures/structures"));
|
|
39
|
+
const nodes_1 = require("../../nodes");
|
|
40
|
+
const _syntax_input_1 = require("../_syntax_input");
|
|
41
|
+
const LOOPS = [
|
|
42
|
+
Structures.Loop,
|
|
43
|
+
Structures.LoopAtScreen,
|
|
44
|
+
Structures.LoopExtract,
|
|
45
|
+
Structures.Do,
|
|
46
|
+
Structures.While,
|
|
47
|
+
Structures.Select,
|
|
48
|
+
Structures.With,
|
|
49
|
+
Structures.Provide,
|
|
50
|
+
];
|
|
51
|
+
// a CLEANUP block cannot contain statements that statically leave it: RETURN, and EXIT, CONTINUE or CHECK
|
|
52
|
+
// that do not belong to a loop inside the block, these end a loop outside the TRY or the processing block
|
|
53
|
+
class Cleanup {
|
|
54
|
+
static runSyntax(node, input) {
|
|
55
|
+
if (input.scope.getOpenABAP()) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const body = node.findDirectStructure(Structures.Body);
|
|
59
|
+
if (body !== undefined) {
|
|
60
|
+
this.walk(body, false, input);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
static walk(node, inLoop, input) {
|
|
64
|
+
for (const child of node.getChildren()) {
|
|
65
|
+
if (child instanceof nodes_1.StructureNode) {
|
|
66
|
+
const stru = child.get();
|
|
67
|
+
// a nested CLEANUP block is checked on its own, macro definitions and test injections do not run here
|
|
68
|
+
if (stru instanceof Structures.Cleanup
|
|
69
|
+
|| stru instanceof Structures.Define
|
|
70
|
+
|| stru instanceof Structures.TestInjection) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
this.walk(child, inLoop || LOOPS.some(l => stru instanceof l), input);
|
|
74
|
+
}
|
|
75
|
+
else if (child instanceof nodes_1.StatementNode) {
|
|
76
|
+
const name = this.leavingStatement(child, inLoop);
|
|
77
|
+
if (name !== undefined) {
|
|
78
|
+
const message = `${name} cannot leave a CLEANUP block`;
|
|
79
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, child.getFirstToken(), message));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
static leavingStatement(node, inLoop) {
|
|
85
|
+
const s = node.get();
|
|
86
|
+
if (s instanceof Statements.Return) {
|
|
87
|
+
return "RETURN";
|
|
88
|
+
}
|
|
89
|
+
else if (inLoop === true) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
else if (s instanceof Statements.Exit && node.findDirectTokenByText("FROM") === undefined) {
|
|
93
|
+
return "EXIT";
|
|
94
|
+
}
|
|
95
|
+
else if (s instanceof Statements.Continue) {
|
|
96
|
+
return "CONTINUE";
|
|
97
|
+
}
|
|
98
|
+
else if (s instanceof Statements.Check) {
|
|
99
|
+
return "CHECK";
|
|
100
|
+
}
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.Cleanup = Cleanup;
|
|
105
|
+
//# sourceMappingURL=cleanup.js.map
|
|
@@ -50,6 +50,7 @@ const type_mesh_1 = require("./structures/type_mesh");
|
|
|
50
50
|
const types_1 = require("./structures/types");
|
|
51
51
|
const statics_1 = require("./structures/statics");
|
|
52
52
|
const constants_1 = require("./structures/constants");
|
|
53
|
+
const cleanup_1 = require("./structures/cleanup");
|
|
53
54
|
const class_definition_1 = require("../types/class_definition");
|
|
54
55
|
const interface_definition_1 = require("../types/interface_definition");
|
|
55
56
|
const delete_memory_1 = require("./statements/delete_memory");
|
|
@@ -191,6 +192,7 @@ const _syntax_input_1 = require("./_syntax_input");
|
|
|
191
192
|
const assert_error_1 = require("./assert_error");
|
|
192
193
|
const field_group_1 = require("./statements/field_group");
|
|
193
194
|
const stuff_1 = require("../../stuff");
|
|
195
|
+
const _loop_table_change_1 = require("./_loop_table_change");
|
|
194
196
|
// -----------------------------------
|
|
195
197
|
const map = {};
|
|
196
198
|
function addToMap(handler) {
|
|
@@ -352,6 +354,7 @@ class SyntaxLogic {
|
|
|
352
354
|
};
|
|
353
355
|
this.issues = [];
|
|
354
356
|
this.deferred = [];
|
|
357
|
+
this.loopTables = new _loop_table_change_1.LoopTableChange();
|
|
355
358
|
this.reg.getDDICReferences().clear(this.object);
|
|
356
359
|
this.reg.getMSAGReferences().clear(this.object);
|
|
357
360
|
if (this.object instanceof objects_1.Program && this.object.isInclude()) {
|
|
@@ -417,6 +420,9 @@ class SyntaxLogic {
|
|
|
417
420
|
this.issues.push(issue);
|
|
418
421
|
}
|
|
419
422
|
traverse(node) {
|
|
423
|
+
const loop = node instanceof nodes_1.StructureNode
|
|
424
|
+
&& node.get() instanceof Structures.Loop
|
|
425
|
+
&& this.loopTables.push(node, this.scope);
|
|
420
426
|
for (const child of node.getChildren()) {
|
|
421
427
|
const isStructure = child instanceof nodes_1.StructureNode;
|
|
422
428
|
const isStatement = child instanceof nodes_1.StatementNode;
|
|
@@ -449,6 +455,9 @@ class SyntaxLogic {
|
|
|
449
455
|
this.traverse(child);
|
|
450
456
|
}
|
|
451
457
|
}
|
|
458
|
+
if (loop === true) {
|
|
459
|
+
this.loopTables.pop();
|
|
460
|
+
}
|
|
452
461
|
}
|
|
453
462
|
/**
|
|
454
463
|
* if this returns true, then the traversal should continue with next child
|
|
@@ -505,6 +514,9 @@ class SyntaxLogic {
|
|
|
505
514
|
// todo: skipped for now
|
|
506
515
|
return true;
|
|
507
516
|
}
|
|
517
|
+
else if (stru instanceof Structures.Cleanup) {
|
|
518
|
+
cleanup_1.Cleanup.runSyntax(node, input);
|
|
519
|
+
}
|
|
508
520
|
return false;
|
|
509
521
|
}
|
|
510
522
|
updateScopeStatement(node) {
|
|
@@ -534,6 +546,7 @@ class SyntaxLogic {
|
|
|
534
546
|
this.scope.addIdentifier(new data_2.Data().runSyntax(node, input));
|
|
535
547
|
return;
|
|
536
548
|
}
|
|
549
|
+
this.loopTables.check(node, input);
|
|
537
550
|
const name = s.constructor.name;
|
|
538
551
|
if (map[name]) {
|
|
539
552
|
map[name].runSyntax(node, input);
|
package/build/src/ddic.js
CHANGED
|
@@ -256,7 +256,7 @@ class DDIC {
|
|
|
256
256
|
lookupDomain(name, dataElement, description) {
|
|
257
257
|
const found = this.reg.getObject("DOMA", name);
|
|
258
258
|
if (found) {
|
|
259
|
-
return { type: found.
|
|
259
|
+
return { type: found.parseDomainType(this.reg, dataElement, description), object: found };
|
|
260
260
|
}
|
|
261
261
|
else if (this.reg.inErrorNamespace(name)) {
|
|
262
262
|
return { type: new Types.UnknownType(name + ", lookupDomain"), object: undefined };
|
|
@@ -81,7 +81,10 @@ class Domain extends _abstract_object_1.AbstractObject {
|
|
|
81
81
|
this.parsedXML = undefined;
|
|
82
82
|
super.setDirty();
|
|
83
83
|
}
|
|
84
|
-
parseType(reg
|
|
84
|
+
parseType(reg) {
|
|
85
|
+
return this.parseDomainType(reg);
|
|
86
|
+
}
|
|
87
|
+
parseDomainType(reg, dataElement, description) {
|
|
85
88
|
// dont cache the DOMA parsed type, they are cached on DTEL level
|
|
86
89
|
// also note that the type carries the name of the DTEL
|
|
87
90
|
if (this.parsedXML === undefined) {
|
package/build/src/registry.js
CHANGED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.AbapdocHtmlTag = exports.AbapdocHtmlTagConf = void 0;
|
|
37
|
+
const Statements = __importStar(require("../abap/2_statements/statements"));
|
|
38
|
+
const issue_1 = require("../issue");
|
|
39
|
+
const _abap_rule_1 = require("./_abap_rule");
|
|
40
|
+
const _basic_rule_config_1 = require("./_basic_rule_config");
|
|
41
|
+
const _irule_1 = require("./_irule");
|
|
42
|
+
const _statement_1 = require("../abap/2_statements/statements/_statement");
|
|
43
|
+
const position_1 = require("../position");
|
|
44
|
+
class AbapdocHtmlTagConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
45
|
+
}
|
|
46
|
+
exports.AbapdocHtmlTagConf = AbapdocHtmlTagConf;
|
|
47
|
+
const ALLOWED = new Set(["p", "em", "strong", "ul", "ol", "li", "br", "h1", "h2", "h3"]);
|
|
48
|
+
class AbapdocHtmlTag extends _abap_rule_1.ABAPRule {
|
|
49
|
+
constructor() {
|
|
50
|
+
super(...arguments);
|
|
51
|
+
this.conf = new AbapdocHtmlTagConf();
|
|
52
|
+
}
|
|
53
|
+
getMetadata() {
|
|
54
|
+
return {
|
|
55
|
+
key: "abapdoc_html_tag",
|
|
56
|
+
title: "Unsupported HTML tag in ABAP Doc",
|
|
57
|
+
shortDescription: `Reports tag-like tokens in ABAP Doc which are not ABAP Doc HTML tags.`,
|
|
58
|
+
extendedInformation: `ABAP Doc is parsed as HTML, a field symbol or a placeholder written as <name> is an
|
|
59
|
+
unsupported and unclosed tag, the system warns and the rendered documentation drops the word.
|
|
60
|
+
|
|
61
|
+
Supported tags are p, em, strong, ul, ol, li, br, h1, h2 and h3, also as closing tags and with attributes.
|
|
62
|
+
|
|
63
|
+
Write <name> to show the angle brackets. A "<" which is not followed by a letter, like "a < b", is not reported.
|
|
64
|
+
|
|
65
|
+
Only checks ABAP Doc inside class definitions and interfaces.`,
|
|
66
|
+
tags: [_irule_1.RuleTag.SingleFile],
|
|
67
|
+
badExample: `INTERFACE zif_foo PUBLIC.
|
|
68
|
+
"! Returns the <name> of the selected row
|
|
69
|
+
METHODS name RETURNING VALUE(result) TYPE string.
|
|
70
|
+
ENDINTERFACE.`,
|
|
71
|
+
goodExample: `INTERFACE zif_foo PUBLIC.
|
|
72
|
+
"! Returns the <name> of the selected row
|
|
73
|
+
METHODS name RETURNING VALUE(result) TYPE string.
|
|
74
|
+
ENDINTERFACE.`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
getConfig() {
|
|
78
|
+
return this.conf;
|
|
79
|
+
}
|
|
80
|
+
setConfig(conf) {
|
|
81
|
+
this.conf = conf;
|
|
82
|
+
}
|
|
83
|
+
runParsed(file) {
|
|
84
|
+
const issues = [];
|
|
85
|
+
let definition = false;
|
|
86
|
+
for (const statement of file.getStatements()) {
|
|
87
|
+
const type = statement.get();
|
|
88
|
+
if (type instanceof Statements.ClassDefinition || type instanceof Statements.Interface) {
|
|
89
|
+
definition = true;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
else if (type instanceof Statements.EndClass || type instanceof Statements.EndInterface) {
|
|
93
|
+
definition = false;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
else if (definition === false || !(type instanceof _statement_1.Comment)) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const token = statement.getFirstToken();
|
|
100
|
+
const str = token.getStr();
|
|
101
|
+
if (str.startsWith(`"!`) === false) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const regex = /<\/?([a-zA-Z][\w-]*)(\s[^<>]*)?\/?>/g;
|
|
105
|
+
let match;
|
|
106
|
+
while ((match = regex.exec(str)) !== null) {
|
|
107
|
+
const name = match[1];
|
|
108
|
+
if (ALLOWED.has(name.toLowerCase())) {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const row = token.getStart().getRow();
|
|
112
|
+
const col = token.getStart().getCol() + match.index;
|
|
113
|
+
const start = new position_1.Position(row, col);
|
|
114
|
+
const end = new position_1.Position(row, col + match[0].length);
|
|
115
|
+
const message = `HTML tag <${name}> is not supported in ABAP Doc, write <${name}>`;
|
|
116
|
+
issues.push(issue_1.Issue.atRange(file, start, end, message, this.getMetadata().key, this.conf.severity));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return issues;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.AbapdocHtmlTag = AbapdocHtmlTag;
|
|
123
|
+
//# sourceMappingURL=abapdoc_html_tag.js.map
|