@abaplint/core 2.120.70 → 2.120.72
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 +10 -0
- package/build/src/abap/1_lexer/lexer.js +1 -1
- package/build/src/abap/1_lexer/lexer_stream.js +8 -0
- package/build/src/abap/2_statements/expressions/string_template_formatting.js +1 -1
- package/build/src/abap/3_structures/structures/_combi.js +61 -112
- package/build/src/abap/5_syntax/basic_types.js +4 -4
- package/build/src/abap/5_syntax/expressions/_check_database_work_area.js +127 -0
- package/build/src/abap/5_syntax/expressions/attribute_name.js +1 -1
- package/build/src/abap/5_syntax/expressions/compare.js +48 -0
- package/build/src/abap/5_syntax/expressions/conv_body.js +2 -2
- package/build/src/abap/5_syntax/expressions/field_chain.js +1 -1
- package/build/src/abap/5_syntax/expressions/form_param.js +1 -1
- package/build/src/abap/5_syntax/expressions/method_parameters.js +2 -2
- package/build/src/abap/5_syntax/expressions/select.js +1 -2
- package/build/src/abap/5_syntax/expressions/source.js +19 -3
- package/build/src/abap/5_syntax/statements/assign.js +15 -1
- package/build/src/abap/5_syntax/statements/insert_database.js +6 -3
- package/build/src/abap/5_syntax/statements/loop.js +1 -1
- package/build/src/abap/5_syntax/statements/modify_database.js +8 -4
- package/build/src/abap/5_syntax/statements/update_database.js +7 -3
- package/build/src/abap/5_syntax/statements/when_type.js +1 -1
- package/build/src/abap/types/class_attributes.js +1 -1
- package/build/src/cds/cds_lexer.js +1 -1
- package/build/src/lsp/help.js +2 -2
- package/build/src/objects/data_element.js +1 -1
- package/build/src/objects/table.js +1 -0
- package/build/src/registry.js +1 -1
- package/build/src/rules/align_pseudo_comments.js +1 -1
- package/build/src/rules/align_type_expressions.js +1 -1
- package/build/src/rules/cds_check_syntax.js +1 -1
- package/build/src/rules/change_if_to_case.js +1 -1
- package/build/src/rules/check_ddic.js +1 -1
- package/build/src/rules/class_attribute_names.js +1 -3
- package/build/src/rules/downport.js +122 -24
- package/build/src/rules/empty_structure.js +26 -0
- package/build/src/rules/functional_writing.js +1 -1
- package/build/src/rules/keyword_case.js +1 -1
- package/build/src/rules/local_class_naming.js +1 -1
- package/build/src/rules/many_parentheses.js +1 -1
- package/build/src/rules/obsolete_statement.js +3 -7
- package/build/src/rules/parser_missing_space.js +1 -2
- package/build/src/rules/prefer_raise_exception_new.js +2 -8
- package/build/src/rules/redundant_conversion.js +59 -2
- package/build/src/rules/xml_consistency.js +25 -1
- package/build/src/utils/form_length_stats.js +1 -1
- package/build/src/utils/method_length_stats.js +1 -1
- package/package.json +1 -1
|
@@ -61,6 +61,7 @@ const _typed_identifier_1 = require("../../types/_typed_identifier");
|
|
|
61
61
|
const _type_utils_1 = require("../_type_utils");
|
|
62
62
|
const _syntax_input_1 = require("../_syntax_input");
|
|
63
63
|
const assert_error_1 = require("../assert_error");
|
|
64
|
+
const version_1 = require("../../../version");
|
|
64
65
|
/*
|
|
65
66
|
* Type interference, valid scenarios:
|
|
66
67
|
* typed = VALUE #( ... ). right hand side must follow left hand type
|
|
@@ -73,7 +74,7 @@ const assert_error_1 = require("../assert_error");
|
|
|
73
74
|
// TODO: refactor all these method parameters to objects, this is getting messy
|
|
74
75
|
class Source {
|
|
75
76
|
static runSyntax(node, input, targetType, writeReference = false, allowGenericDeference = false, readReference = true) {
|
|
76
|
-
var _a;
|
|
77
|
+
var _a, _b, _c, _d;
|
|
77
78
|
if (node === undefined) {
|
|
78
79
|
return undefined;
|
|
79
80
|
}
|
|
@@ -151,7 +152,7 @@ class Source {
|
|
|
151
152
|
case "CONV":
|
|
152
153
|
{
|
|
153
154
|
const foundType = this.determineType(node, input, targetType);
|
|
154
|
-
const bodyType = conv_body_1.ConvBody.runSyntax(node.findDirectExpression(Expressions.ConvBody), input);
|
|
155
|
+
const bodyType = conv_body_1.ConvBody.runSyntax(node.findDirectExpression(Expressions.ConvBody), input, foundType);
|
|
155
156
|
const inferred = (_a = node.findDirectExpression(Expressions.TypeNameOrInfer)) === null || _a === void 0 ? void 0 : _a.concatTokens();
|
|
156
157
|
if (new _type_utils_1.TypeUtils(input.scope).isConvable(foundType, bodyType) === false) {
|
|
157
158
|
const message = `CONV: Types not compatible, ${foundType === null || foundType === void 0 ? void 0 : foundType.constructor.name}, ${bodyType === null || bodyType === void 0 ? void 0 : bodyType.constructor.name}`;
|
|
@@ -168,7 +169,13 @@ class Source {
|
|
|
168
169
|
this.traverseRemainingChildren(children, input);
|
|
169
170
|
return bodyType;
|
|
170
171
|
}
|
|
171
|
-
|
|
172
|
+
const bodySource = (_b = node.findDirectExpression(Expressions.ConvBody)) === null || _b === void 0 ? void 0 : _b.findDirectExpression(Expressions.Source);
|
|
173
|
+
const nestedType = (_c = bodySource === null || bodySource === void 0 ? void 0 : bodySource.findDirectExpression(Expressions.TypeNameOrInfer)) === null || _c === void 0 ? void 0 : _c.concatTokens();
|
|
174
|
+
// CONV # passes its target type into a nested inferred constructor, so
|
|
175
|
+
// showing both inferred types would produce duplicate inlay hints.
|
|
176
|
+
if (!(inferred === "#" && nestedType === "#")) {
|
|
177
|
+
this.addIfInferred(node, input, foundType);
|
|
178
|
+
}
|
|
172
179
|
this.traverseRemainingChildren(children, input);
|
|
173
180
|
return foundType;
|
|
174
181
|
}
|
|
@@ -225,6 +232,15 @@ class Source {
|
|
|
225
232
|
case "CORRESPONDING":
|
|
226
233
|
{
|
|
227
234
|
const foundType = this.determineType(node, input, targetType);
|
|
235
|
+
if ((foundType === null || foundType === void 0 ? void 0 : foundType.isGeneric()) === true
|
|
236
|
+
&& ((_d = node.findDirectExpression(Expressions.TypeNameOrInfer)) === null || _d === void 0 ? void 0 : _d.concatTokens()) === "#"
|
|
237
|
+
&& !(0, version_1.releaseAtLeast)(input.scope.getRelease(), version_1.Release.v756)
|
|
238
|
+
&& input.scope.getLanguageVersion() !== version_1.LanguageVersion.Cloud
|
|
239
|
+
&& !input.scope.getOpenABAP()) {
|
|
240
|
+
const message = "CORRESPONDING #, the type of the target is generic";
|
|
241
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
242
|
+
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
243
|
+
}
|
|
228
244
|
corresponding_body_1.CorrespondingBody.runSyntax(node.findDirectExpression(Expressions.CorrespondingBody), input, foundType);
|
|
229
245
|
this.addIfInferred(node, input, foundType);
|
|
230
246
|
return foundType;
|
|
@@ -41,6 +41,7 @@ const basic_1 = require("../../types/basic");
|
|
|
41
41
|
const dynamic_1 = require("../expressions/dynamic");
|
|
42
42
|
const _type_utils_1 = require("../_type_utils");
|
|
43
43
|
const _syntax_input_1 = require("../_syntax_input");
|
|
44
|
+
const version_1 = require("../../../version");
|
|
44
45
|
class Assign {
|
|
45
46
|
runSyntax(node, input) {
|
|
46
47
|
var _a;
|
|
@@ -48,7 +49,7 @@ class Assign {
|
|
|
48
49
|
const isComponent = ((_a = assignSource === null || assignSource === void 0 ? void 0 : assignSource.getFirstChild()) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase()) === "COMPONENT";
|
|
49
50
|
const sources = (assignSource === null || assignSource === void 0 ? void 0 : assignSource.findDirectExpressionsMulti([Expressions.Source, Expressions.SimpleSource3])) || [];
|
|
50
51
|
const theSource = sources[sources.length - 1];
|
|
51
|
-
let sourceType
|
|
52
|
+
let sourceType;
|
|
52
53
|
const firstAssign = assignSource === null || assignSource === void 0 ? void 0 : assignSource.getChildren()[0];
|
|
53
54
|
const secondAssign = assignSource === null || assignSource === void 0 ? void 0 : assignSource.getChildren()[1];
|
|
54
55
|
const thirdAssign = assignSource === null || assignSource === void 0 ? void 0 : assignSource.getChildren()[2];
|
|
@@ -64,6 +65,19 @@ class Assign {
|
|
|
64
65
|
}
|
|
65
66
|
else {
|
|
66
67
|
sourceType = source_1.Source.runSyntax(theSource, input, undefined, false, isComponent === false);
|
|
68
|
+
if ((secondAssign === null || secondAssign === void 0 ? void 0 : secondAssign.concatTokens()) === "->"
|
|
69
|
+
&& (thirdAssign === null || thirdAssign === void 0 ? void 0 : thirdAssign.get()) instanceof Expressions.Dynamic
|
|
70
|
+
&& (sourceType === null || sourceType === void 0 ? void 0 : sourceType.isGeneric()) === true
|
|
71
|
+
&& !(sourceType instanceof basic_1.DataReference)
|
|
72
|
+
&& !(sourceType instanceof basic_1.ObjectReferenceType)
|
|
73
|
+
&& !(sourceType instanceof basic_1.GenericObjectReferenceType)
|
|
74
|
+
&& !(0, version_1.releaseAtLeast)(input.scope.getRelease(), version_1.Release.v756)
|
|
75
|
+
&& input.scope.getLanguageVersion() !== version_1.LanguageVersion.Cloud
|
|
76
|
+
&& !input.scope.getOpenABAP()) {
|
|
77
|
+
const message = `"${theSource.concatTokens()}" is not a reference variable`;
|
|
78
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
67
81
|
}
|
|
68
82
|
if ((assignSource === null || assignSource === void 0 ? void 0 : assignSource.getChildren().length) === 5
|
|
69
83
|
&& isComponent) {
|
|
@@ -38,20 +38,23 @@ const Expressions = __importStar(require("../../2_statements/expressions"));
|
|
|
38
38
|
const source_1 = require("../expressions/source");
|
|
39
39
|
const dynamic_1 = require("../expressions/dynamic");
|
|
40
40
|
const database_table_1 = require("../expressions/database_table");
|
|
41
|
+
const _check_database_work_area_1 = require("../expressions/_check_database_work_area");
|
|
41
42
|
class InsertDatabase {
|
|
42
43
|
runSyntax(node, input) {
|
|
44
|
+
const sourceTypes = new Map();
|
|
43
45
|
for (const s of node.findAllExpressions(Expressions.Source)) {
|
|
44
|
-
source_1.Source.runSyntax(s, input);
|
|
46
|
+
sourceTypes.set(s, source_1.Source.runSyntax(s, input));
|
|
45
47
|
}
|
|
46
48
|
for (const s of node.findAllExpressions(Expressions.SimpleSource3)) {
|
|
47
|
-
source_1.Source.runSyntax(s, input);
|
|
49
|
+
sourceTypes.set(s, source_1.Source.runSyntax(s, input));
|
|
48
50
|
}
|
|
49
51
|
for (const d of node.findAllExpressions(Expressions.Dynamic)) {
|
|
50
52
|
dynamic_1.Dynamic.runSyntax(d, input);
|
|
51
53
|
}
|
|
52
54
|
const dbtab = node.findFirstExpression(Expressions.DatabaseTable);
|
|
53
55
|
if (dbtab !== undefined) {
|
|
54
|
-
database_table_1.DatabaseTable.runSyntax(dbtab, input);
|
|
56
|
+
const dbSource = database_table_1.DatabaseTable.runSyntax(dbtab, input);
|
|
57
|
+
(0, _check_database_work_area_1.checkDatabaseWorkArea)(node, dbSource, sourceTypes, input);
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
}
|
|
@@ -130,7 +130,7 @@ class Loop {
|
|
|
130
130
|
&& topType instanceof basic_1.TableType) {
|
|
131
131
|
// https://github.com/abap2xlsx/abap2xlsx/issues/1341
|
|
132
132
|
const keyName = node.findExpressionAfterToken("KEY");
|
|
133
|
-
let key
|
|
133
|
+
let key;
|
|
134
134
|
const name = (keyName === null || keyName === void 0 ? void 0 : keyName.get()) instanceof Expressions.SimpleName ? keyName.getFirstToken().getStr().toUpperCase() : undefined;
|
|
135
135
|
// it might be dynamic, in that case we cannot check anything; and
|
|
136
136
|
// primary_key is the predefined name of the primary key every table has
|
|
@@ -39,11 +39,13 @@ const dynamic_1 = require("../expressions/dynamic");
|
|
|
39
39
|
const database_table_1 = require("../expressions/database_table");
|
|
40
40
|
const source_1 = require("../expressions/source");
|
|
41
41
|
const _reference_1 = require("../_reference");
|
|
42
|
+
const _check_database_work_area_1 = require("../expressions/_check_database_work_area");
|
|
42
43
|
class ModifyDatabase {
|
|
43
44
|
runSyntax(node, input) {
|
|
44
45
|
for (const d of node.findAllExpressions(Expressions.Dynamic)) {
|
|
45
46
|
dynamic_1.Dynamic.runSyntax(d, input);
|
|
46
47
|
}
|
|
48
|
+
let dbSource = undefined;
|
|
47
49
|
const dbtab = node.findFirstExpression(Expressions.DatabaseTable);
|
|
48
50
|
if (dbtab !== undefined) {
|
|
49
51
|
if (node.getChildren().length === 5) {
|
|
@@ -52,19 +54,21 @@ class ModifyDatabase {
|
|
|
52
54
|
input.scope.addReference(dbtab.getFirstToken(), found, _reference_1.ReferenceType.DataWriteReference, input.filename);
|
|
53
55
|
}
|
|
54
56
|
else {
|
|
55
|
-
database_table_1.DatabaseTable.runSyntax(dbtab, input);
|
|
57
|
+
dbSource = database_table_1.DatabaseTable.runSyntax(dbtab, input);
|
|
56
58
|
}
|
|
57
59
|
}
|
|
58
60
|
else {
|
|
59
|
-
database_table_1.DatabaseTable.runSyntax(dbtab, input);
|
|
61
|
+
dbSource = database_table_1.DatabaseTable.runSyntax(dbtab, input);
|
|
60
62
|
}
|
|
61
63
|
}
|
|
64
|
+
const sourceTypes = new Map();
|
|
62
65
|
for (const s of node.findAllExpressions(Expressions.Source)) {
|
|
63
|
-
source_1.Source.runSyntax(s, input);
|
|
66
|
+
sourceTypes.set(s, source_1.Source.runSyntax(s, input));
|
|
64
67
|
}
|
|
65
68
|
for (const s of node.findAllExpressions(Expressions.SimpleSource3)) {
|
|
66
|
-
source_1.Source.runSyntax(s, input);
|
|
69
|
+
sourceTypes.set(s, source_1.Source.runSyntax(s, input));
|
|
67
70
|
}
|
|
71
|
+
(0, _check_database_work_area_1.checkDatabaseWorkArea)(node, dbSource, sourceTypes, input);
|
|
68
72
|
}
|
|
69
73
|
}
|
|
70
74
|
exports.ModifyDatabase = ModifyDatabase;
|
|
@@ -43,11 +43,13 @@ const identifier_1 = require("../../1_lexer/tokens/identifier");
|
|
|
43
43
|
const database_table_1 = require("../expressions/database_table");
|
|
44
44
|
const dynamic_1 = require("../expressions/dynamic");
|
|
45
45
|
const _check_database_fields_1 = require("../expressions/_check_database_fields");
|
|
46
|
+
const _check_database_work_area_1 = require("../expressions/_check_database_work_area");
|
|
46
47
|
class UpdateDatabase {
|
|
47
48
|
runSyntax(node, input) {
|
|
49
|
+
let dbSource = undefined;
|
|
48
50
|
const dbtab = node.findFirstExpression(Expressions.DatabaseTable);
|
|
49
51
|
if (dbtab !== undefined) {
|
|
50
|
-
|
|
52
|
+
dbSource = database_table_1.DatabaseTable.runSyntax(dbtab, input);
|
|
51
53
|
const fields = node.findAllExpressions(Expressions.SQLFieldAndValue)
|
|
52
54
|
.flatMap(fieldAndValue => fieldAndValue.findDirectExpressions(Expressions.SQLFieldName))
|
|
53
55
|
.map(field => field.concatTokens().toUpperCase());
|
|
@@ -70,15 +72,17 @@ class UpdateDatabase {
|
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
}
|
|
75
|
+
const sourceTypes = new Map();
|
|
73
76
|
for (const s of node.findAllExpressions(Expressions.Source)) {
|
|
74
|
-
source_1.Source.runSyntax(s, input);
|
|
77
|
+
sourceTypes.set(s, source_1.Source.runSyntax(s, input));
|
|
75
78
|
}
|
|
76
79
|
for (const s of node.findAllExpressions(Expressions.SimpleSource3)) {
|
|
77
|
-
source_1.Source.runSyntax(s, input);
|
|
80
|
+
sourceTypes.set(s, source_1.Source.runSyntax(s, input));
|
|
78
81
|
}
|
|
79
82
|
for (const d of node.findAllExpressions(Expressions.Dynamic)) {
|
|
80
83
|
dynamic_1.Dynamic.runSyntax(d, input);
|
|
81
84
|
}
|
|
85
|
+
(0, _check_database_work_area_1.checkDatabaseWorkArea)(node, dbSource, sourceTypes, input);
|
|
82
86
|
if (input.scope.getType() === _scope_type_1.ScopeType.OpenSQL) {
|
|
83
87
|
input.scope.pop(node.getLastToken().getEnd());
|
|
84
88
|
}
|
|
@@ -47,7 +47,7 @@ class WhenType {
|
|
|
47
47
|
if (nameToken === undefined) {
|
|
48
48
|
return undefined;
|
|
49
49
|
}
|
|
50
|
-
let type
|
|
50
|
+
let type;
|
|
51
51
|
const className = nameToken.getStr().toUpperCase();
|
|
52
52
|
const found = input.scope.existsObject(className);
|
|
53
53
|
if (found === null || found === void 0 ? void 0 : found.id) {
|
package/build/src/lsp/help.js
CHANGED
|
@@ -50,7 +50,7 @@ class Help {
|
|
|
50
50
|
return content;
|
|
51
51
|
}
|
|
52
52
|
static dumpABAP(file, reg, textDocument, position) {
|
|
53
|
-
let content
|
|
53
|
+
let content;
|
|
54
54
|
content = `
|
|
55
55
|
<a href="#_tokens" rel="no-refresh">Tokens</a> |
|
|
56
56
|
<a href="#_statements" rel="no-refresh">Statements</a> |
|
|
@@ -83,7 +83,7 @@ class Help {
|
|
|
83
83
|
return `<h3 id="_info">Info Dump</h3><pre>` + text + "</pre>";
|
|
84
84
|
}
|
|
85
85
|
static cursorInformation(reg, textDocument, position, file) {
|
|
86
|
-
let ret
|
|
86
|
+
let ret;
|
|
87
87
|
const found = _lsp_utils_1.LSPUtils.findCursor(reg, { textDocument, position });
|
|
88
88
|
if (found !== undefined) {
|
|
89
89
|
ret = "Statement: " + this.linkToStatement(found.snode.get()) + "<br>\n" +
|
|
@@ -121,7 +121,7 @@ class DataElement extends _abstract_object_1.AbstractObject {
|
|
|
121
121
|
}
|
|
122
122
|
parseType(reg) {
|
|
123
123
|
const references = [];
|
|
124
|
-
let lookup
|
|
124
|
+
let lookup;
|
|
125
125
|
this.parse();
|
|
126
126
|
if (this.parsedXML === undefined) {
|
|
127
127
|
lookup = { type: new Types.UnknownType("Data Element " + this.getName() + ", parser error") };
|
package/build/src/registry.js
CHANGED
|
@@ -54,7 +54,7 @@ class AlignPseudoComments extends _abap_rule_1.ABAPRule {
|
|
|
54
54
|
}
|
|
55
55
|
const col = firstCommentToken.getStart().getCol();
|
|
56
56
|
if (previousEnd.getCol() < expectedColumn && col !== expectedColumn) {
|
|
57
|
-
let fix
|
|
57
|
+
let fix;
|
|
58
58
|
if (col < expectedColumn) {
|
|
59
59
|
fix = edit_helper_1.EditHelper.insertAt(file, firstCommentToken.getStart(), " ".repeat(expectedColumn - col));
|
|
60
60
|
}
|
|
@@ -138,7 +138,7 @@ ENDINTERFACE.`,
|
|
|
138
138
|
if (f.after.getCol() === column) {
|
|
139
139
|
continue;
|
|
140
140
|
}
|
|
141
|
-
let fix
|
|
141
|
+
let fix;
|
|
142
142
|
if (f.after.getCol() < column) {
|
|
143
143
|
fix = edit_helper_1.EditHelper.insertAt(file, f.after, " ".repeat(column - f.after.getCol()));
|
|
144
144
|
}
|
|
@@ -15,7 +15,7 @@ exports.CDSCheckSyntaxConf = CDSCheckSyntaxConf;
|
|
|
15
15
|
const KNOWN_QUAN_DATA_ELEMENTS = ["MENGE_D"];
|
|
16
16
|
const KNOWN_CURR_DATA_ELEMENTS = ["BWERT", "DZWERT"];
|
|
17
17
|
// Reserved names, cannot be used as element names, see DDIC table TRESE
|
|
18
|
-
const RESERVED_ELEMENT_NAMES = ["BEGIN", "NUMBER", "POSITION"];
|
|
18
|
+
const RESERVED_ELEMENT_NAMES = ["BEGIN", "NUMBER", "POSITION", "ZONE", "HANDLER", "SECTION"];
|
|
19
19
|
const MAX_LABEL_LENGTH = 40;
|
|
20
20
|
// Annotations which are not supported in CDS view entities
|
|
21
21
|
const VIEW_ENTITY_FORBIDDEN_ANNOTATIONS = ["Semantics.unitOfMeasure", "Semantics.currencyCode"];
|
|
@@ -59,7 +59,6 @@ ENDCLASS.`,
|
|
|
59
59
|
this.conf = conf;
|
|
60
60
|
}
|
|
61
61
|
runParsed(file, obj) {
|
|
62
|
-
let issues = [];
|
|
63
62
|
if (this.conf.patternKind === undefined) {
|
|
64
63
|
this.conf.patternKind = "required";
|
|
65
64
|
}
|
|
@@ -80,8 +79,7 @@ ENDCLASS.`,
|
|
|
80
79
|
attributes = attributes.concat(intfDef.attributes);
|
|
81
80
|
}
|
|
82
81
|
}
|
|
83
|
-
|
|
84
|
-
return issues;
|
|
82
|
+
return this.checkAttributes(attributes);
|
|
85
83
|
}
|
|
86
84
|
checkAttributes(attr) {
|
|
87
85
|
if (attr === undefined) {
|