@abaplint/core 2.120.71 → 2.120.73
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/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/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/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/generic_regex.js +86 -0
- package/build/src/rules/index.js +1 -0
- 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/xml_consistency.js +16 -0
- 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
package/build/abaplint.d.ts
CHANGED
|
@@ -3681,6 +3681,14 @@ declare interface IMatch {
|
|
|
3681
3681
|
errorMatched: number;
|
|
3682
3682
|
}
|
|
3683
3683
|
|
|
3684
|
+
/** A match from an index: statements[index] up to statements[next] were matched */
|
|
3685
|
+
declare interface IMatchAt {
|
|
3686
|
+
next: number;
|
|
3687
|
+
error: boolean;
|
|
3688
|
+
errorDescription: string;
|
|
3689
|
+
errorMatched: number;
|
|
3690
|
+
}
|
|
3691
|
+
|
|
3684
3692
|
export declare interface IMethodDefinition extends Identifier {
|
|
3685
3693
|
getVisibility(): Visibility;
|
|
3686
3694
|
isRedefinition(): boolean;
|
|
@@ -4357,6 +4365,7 @@ declare interface IStructureRunnable {
|
|
|
4357
4365
|
toRailroad(): string;
|
|
4358
4366
|
getUsing(): string[];
|
|
4359
4367
|
run(statements: StatementNode[], parent: INode): IMatch;
|
|
4368
|
+
runAt(statements: StatementNode[], index: number, parent: INode): IMatchAt;
|
|
4360
4369
|
first(): string[];
|
|
4361
4370
|
}
|
|
4362
4371
|
|
|
@@ -7831,6 +7840,7 @@ declare class Table extends AbstractObject {
|
|
|
7831
7840
|
PRECFIELD?: string;
|
|
7832
7841
|
LENG?: string;
|
|
7833
7842
|
INTLEN?: string;
|
|
7843
|
+
INTTYPE?: string;
|
|
7834
7844
|
DATATYPE?: string;
|
|
7835
7845
|
DECIMALS?: string;
|
|
7836
7846
|
KEYFLAG?: string;
|
|
@@ -343,7 +343,7 @@ class Lexer {
|
|
|
343
343
|
else if (this.m === ModeTemplate
|
|
344
344
|
&& this.buffer.length() > 1
|
|
345
345
|
&& (current === CH_PIPE || current === CH_LBRACE)
|
|
346
|
-
&&
|
|
346
|
+
&& stream.countPrevious(CH_BACKSLASH) % 2 === 0) {
|
|
347
347
|
// end of template
|
|
348
348
|
if (current === CH_LBRACE || AFTER_LITERAL.has(ahead)) {
|
|
349
349
|
this.add();
|
|
@@ -46,6 +46,14 @@ class LexerStream {
|
|
|
46
46
|
}
|
|
47
47
|
return this.raw.charCodeAt(o);
|
|
48
48
|
}
|
|
49
|
+
/** number of consecutive occurrences of the character directly before the current one */
|
|
50
|
+
countPrevious(code) {
|
|
51
|
+
let count = 0;
|
|
52
|
+
for (let o = this.offset - 1; o >= 0 && this.raw.charCodeAt(o) === code; o--) {
|
|
53
|
+
count++;
|
|
54
|
+
}
|
|
55
|
+
return count;
|
|
56
|
+
}
|
|
49
57
|
currentChar() {
|
|
50
58
|
if (this.offset < 0) {
|
|
51
59
|
return NL; // simulate newline at start of file to handle star(*) comments
|
|
@@ -9,6 +9,21 @@ exports.sta = sta;
|
|
|
9
9
|
exports.sub = sub;
|
|
10
10
|
const nodes_1 = require("../../nodes");
|
|
11
11
|
const _statement_1 = require("../../2_statements/statements/_statement");
|
|
12
|
+
function toMatch(statements, m) {
|
|
13
|
+
return {
|
|
14
|
+
matched: statements.slice(0, m.next),
|
|
15
|
+
unmatched: statements.slice(m.next),
|
|
16
|
+
error: m.error,
|
|
17
|
+
errorDescription: m.errorDescription,
|
|
18
|
+
errorMatched: m.errorMatched,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function success(next) {
|
|
22
|
+
return { next, error: false, errorDescription: "", errorMatched: 0 };
|
|
23
|
+
}
|
|
24
|
+
function failure(next, errorDescription, errorMatched) {
|
|
25
|
+
return { next, error: true, errorDescription, errorMatched };
|
|
26
|
+
}
|
|
12
27
|
class Sequence {
|
|
13
28
|
constructor(list) {
|
|
14
29
|
if (list.length < 2) {
|
|
@@ -27,36 +42,18 @@ class Sequence {
|
|
|
27
42
|
return this.list[0].first();
|
|
28
43
|
}
|
|
29
44
|
run(statements, parent) {
|
|
30
|
-
|
|
31
|
-
|
|
45
|
+
return toMatch(statements, this.runAt(statements, 0, parent));
|
|
46
|
+
}
|
|
47
|
+
runAt(statements, index, parent) {
|
|
48
|
+
let next = index;
|
|
32
49
|
for (const i of this.list) {
|
|
33
|
-
const match = i.
|
|
50
|
+
const match = i.runAt(statements, next, parent);
|
|
34
51
|
if (match.error) {
|
|
35
|
-
return
|
|
36
|
-
matched: [],
|
|
37
|
-
unmatched: statements,
|
|
38
|
-
error: true,
|
|
39
|
-
errorDescription: match.errorDescription,
|
|
40
|
-
errorMatched: out.length,
|
|
41
|
-
};
|
|
52
|
+
return failure(index, match.errorDescription, next - index);
|
|
42
53
|
}
|
|
43
|
-
|
|
44
|
-
out.push(...match.matched);
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
// avoid using the spread operator, it might trigger "Maximum call stack size exceeded"
|
|
48
|
-
// when the number of matched elements is very large
|
|
49
|
-
out = out.concat(match.matched);
|
|
50
|
-
}
|
|
51
|
-
inn = match.unmatched;
|
|
54
|
+
next = match.next;
|
|
52
55
|
}
|
|
53
|
-
return
|
|
54
|
-
matched: out,
|
|
55
|
-
unmatched: inn,
|
|
56
|
-
error: false,
|
|
57
|
-
errorDescription: "",
|
|
58
|
-
errorMatched: 0,
|
|
59
|
-
};
|
|
56
|
+
return success(next);
|
|
60
57
|
}
|
|
61
58
|
}
|
|
62
59
|
// Note that the Alternative does not nessesarily return the first in the alternative
|
|
@@ -95,21 +92,18 @@ class Alternative {
|
|
|
95
92
|
return this.list.reduce((a, c) => { return a.concat(c.getUsing()); }, []);
|
|
96
93
|
}
|
|
97
94
|
run(statements, parent) {
|
|
95
|
+
return toMatch(statements, this.runAt(statements, 0, parent));
|
|
96
|
+
}
|
|
97
|
+
runAt(statements, index, parent) {
|
|
98
98
|
this.setupMap();
|
|
99
99
|
let count = 0;
|
|
100
100
|
let countError = "";
|
|
101
|
-
if (statements.length
|
|
102
|
-
return
|
|
103
|
-
matched: [],
|
|
104
|
-
unmatched: statements,
|
|
105
|
-
error: true,
|
|
106
|
-
errorDescription: countError,
|
|
107
|
-
errorMatched: count,
|
|
108
|
-
};
|
|
101
|
+
if (index >= statements.length) {
|
|
102
|
+
return failure(index, countError, count);
|
|
109
103
|
}
|
|
110
|
-
const token = statements[
|
|
104
|
+
const token = statements[index].getFirstToken().getStr().toUpperCase();
|
|
111
105
|
for (const i of this.map[token] || []) {
|
|
112
|
-
const match = i.
|
|
106
|
+
const match = i.runAt(statements, index, parent);
|
|
113
107
|
if (match.error === false) {
|
|
114
108
|
return match;
|
|
115
109
|
}
|
|
@@ -119,7 +113,7 @@ class Alternative {
|
|
|
119
113
|
}
|
|
120
114
|
}
|
|
121
115
|
for (const i of this.map[""] || []) {
|
|
122
|
-
const match = i.
|
|
116
|
+
const match = i.runAt(statements, index, parent);
|
|
123
117
|
if (match.error === false) {
|
|
124
118
|
return match;
|
|
125
119
|
}
|
|
@@ -129,22 +123,10 @@ class Alternative {
|
|
|
129
123
|
}
|
|
130
124
|
}
|
|
131
125
|
if (count === 0) {
|
|
132
|
-
return
|
|
133
|
-
matched: [],
|
|
134
|
-
unmatched: statements,
|
|
135
|
-
error: true,
|
|
136
|
-
errorDescription: "Unexpected code structure",
|
|
137
|
-
errorMatched: count,
|
|
138
|
-
};
|
|
126
|
+
return failure(index, "Unexpected code structure", count);
|
|
139
127
|
}
|
|
140
128
|
else {
|
|
141
|
-
return
|
|
142
|
-
matched: [],
|
|
143
|
-
unmatched: statements,
|
|
144
|
-
error: true,
|
|
145
|
-
errorDescription: countError,
|
|
146
|
-
errorMatched: count,
|
|
147
|
-
};
|
|
129
|
+
return failure(index, countError, count);
|
|
148
130
|
}
|
|
149
131
|
}
|
|
150
132
|
}
|
|
@@ -159,7 +141,10 @@ class Optional {
|
|
|
159
141
|
return this.obj.getUsing();
|
|
160
142
|
}
|
|
161
143
|
run(statements, parent) {
|
|
162
|
-
|
|
144
|
+
return toMatch(statements, this.runAt(statements, 0, parent));
|
|
145
|
+
}
|
|
146
|
+
runAt(statements, index, parent) {
|
|
147
|
+
const ret = this.obj.runAt(statements, index, parent);
|
|
163
148
|
ret.error = false;
|
|
164
149
|
return ret;
|
|
165
150
|
}
|
|
@@ -178,48 +163,24 @@ class Star {
|
|
|
178
163
|
return this.obj.getUsing();
|
|
179
164
|
}
|
|
180
165
|
run(statements, parent) {
|
|
181
|
-
|
|
182
|
-
|
|
166
|
+
return toMatch(statements, this.runAt(statements, 0, parent));
|
|
167
|
+
}
|
|
168
|
+
runAt(statements, index, parent) {
|
|
169
|
+
let next = index;
|
|
183
170
|
while (true) {
|
|
184
|
-
if (
|
|
185
|
-
return
|
|
186
|
-
matched: out,
|
|
187
|
-
unmatched: inn,
|
|
188
|
-
error: false,
|
|
189
|
-
errorDescription: "",
|
|
190
|
-
errorMatched: 0,
|
|
191
|
-
};
|
|
171
|
+
if (next >= statements.length) {
|
|
172
|
+
return success(next);
|
|
192
173
|
}
|
|
193
|
-
const match = this.obj.
|
|
174
|
+
const match = this.obj.runAt(statements, next, parent);
|
|
194
175
|
if (match.error === true) {
|
|
195
176
|
if (match.errorMatched > 0) {
|
|
196
|
-
return
|
|
197
|
-
matched: out,
|
|
198
|
-
unmatched: inn,
|
|
199
|
-
error: true,
|
|
200
|
-
errorDescription: match.errorDescription,
|
|
201
|
-
errorMatched: match.errorMatched,
|
|
202
|
-
};
|
|
177
|
+
return failure(next, match.errorDescription, match.errorMatched);
|
|
203
178
|
}
|
|
204
179
|
else {
|
|
205
|
-
return
|
|
206
|
-
matched: out,
|
|
207
|
-
unmatched: inn,
|
|
208
|
-
error: false,
|
|
209
|
-
errorDescription: "",
|
|
210
|
-
errorMatched: 0,
|
|
211
|
-
};
|
|
180
|
+
return success(next);
|
|
212
181
|
}
|
|
213
182
|
}
|
|
214
|
-
|
|
215
|
-
out.push(...match.matched);
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
// avoid using the spread operator, it might trigger "Maximum call stack size exceeded"
|
|
219
|
-
// when the number of matched elements is very large
|
|
220
|
-
out = out.concat(match.matched);
|
|
221
|
-
}
|
|
222
|
-
inn = match.unmatched;
|
|
183
|
+
next = match.next;
|
|
223
184
|
}
|
|
224
185
|
}
|
|
225
186
|
first() {
|
|
@@ -248,10 +209,13 @@ class SubStructure {
|
|
|
248
209
|
}
|
|
249
210
|
}
|
|
250
211
|
run(statements, parent) {
|
|
212
|
+
return toMatch(statements, this.runAt(statements, 0, parent));
|
|
213
|
+
}
|
|
214
|
+
runAt(statements, index, parent) {
|
|
251
215
|
const nparent = new nodes_1.StructureNode(this.s);
|
|
252
216
|
this.setupMatcher();
|
|
253
|
-
const ret = this.matcher.
|
|
254
|
-
if (ret.
|
|
217
|
+
const ret = this.matcher.runAt(statements, index, nparent);
|
|
218
|
+
if (ret.next === index) {
|
|
255
219
|
ret.error = true;
|
|
256
220
|
}
|
|
257
221
|
else {
|
|
@@ -281,33 +245,18 @@ class SubStatement {
|
|
|
281
245
|
return this.obj.name;
|
|
282
246
|
}
|
|
283
247
|
run(statements, parent) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
errorDescription: "Expected " + this.className().toUpperCase(),
|
|
290
|
-
errorMatched: 0,
|
|
291
|
-
};
|
|
248
|
+
return toMatch(statements, this.runAt(statements, 0, parent));
|
|
249
|
+
}
|
|
250
|
+
runAt(statements, index, parent) {
|
|
251
|
+
if (index >= statements.length) {
|
|
252
|
+
return failure(statements.length, "Expected " + this.className().toUpperCase(), 0);
|
|
292
253
|
}
|
|
293
|
-
else if (statements[
|
|
294
|
-
parent.addChild(statements[
|
|
295
|
-
return
|
|
296
|
-
matched: [statements[0]],
|
|
297
|
-
unmatched: statements.splice(1),
|
|
298
|
-
error: false,
|
|
299
|
-
errorDescription: "",
|
|
300
|
-
errorMatched: 0,
|
|
301
|
-
};
|
|
254
|
+
else if (statements[index].get() instanceof this.obj) {
|
|
255
|
+
parent.addChild(statements[index]);
|
|
256
|
+
return success(index + 1);
|
|
302
257
|
}
|
|
303
258
|
else {
|
|
304
|
-
return
|
|
305
|
-
matched: [],
|
|
306
|
-
unmatched: statements,
|
|
307
|
-
error: true,
|
|
308
|
-
errorDescription: "Expected " + this.className().toUpperCase(),
|
|
309
|
-
errorMatched: 0,
|
|
310
|
-
};
|
|
259
|
+
return failure(index, "Expected " + this.className().toUpperCase(), 0);
|
|
311
260
|
}
|
|
312
261
|
}
|
|
313
262
|
}
|
|
@@ -153,7 +153,7 @@ class BasicTypes {
|
|
|
153
153
|
if (children.length === 0) {
|
|
154
154
|
return new Types.UnknownType("Type error, could not resolve \"" + fullName + "\", resolveLikeName1");
|
|
155
155
|
}
|
|
156
|
-
let type
|
|
156
|
+
let type;
|
|
157
157
|
if (children[1] && (children[1].getFirstToken().getStr() === "=>" || children[1].getFirstToken().getStr() === "->")) {
|
|
158
158
|
type = field_chain_1.FieldChain.runSyntax(chain, this.input, _reference_1.ReferenceType.TypeReference);
|
|
159
159
|
}
|
|
@@ -416,7 +416,7 @@ class BasicTypes {
|
|
|
416
416
|
primaryKey: primaryKey,
|
|
417
417
|
secondary: secondaryKeys,
|
|
418
418
|
};
|
|
419
|
-
let found
|
|
419
|
+
let found;
|
|
420
420
|
if (text.startsWith("TYPE TABLE OF REF TO ")
|
|
421
421
|
|| text.startsWith("TYPE STANDARD TABLE OF REF TO ")
|
|
422
422
|
|| text.startsWith("TYPE SORTED TABLE OF REF TO ")
|
|
@@ -554,7 +554,7 @@ class BasicTypes {
|
|
|
554
554
|
name = typeName === null || typeName === void 0 ? void 0 : typeName.concatTokens();
|
|
555
555
|
}
|
|
556
556
|
const type = this.resolveLikeName(e, false);
|
|
557
|
-
let row
|
|
557
|
+
let row;
|
|
558
558
|
if (type === undefined) {
|
|
559
559
|
return new Types.UnknownType("Type error, could not resolve \"" + name + "\", parseType");
|
|
560
560
|
}
|
|
@@ -749,7 +749,7 @@ class BasicTypes {
|
|
|
749
749
|
rest = split[1];
|
|
750
750
|
}
|
|
751
751
|
const subs = rest.split("-");
|
|
752
|
-
let foundType
|
|
752
|
+
let foundType;
|
|
753
753
|
if (className && chainText.includes("=>")) {
|
|
754
754
|
const split = chainText.split("=>");
|
|
755
755
|
const className = split[0];
|
|
@@ -0,0 +1,127 @@
|
|
|
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.checkDatabaseWorkArea = checkDatabaseWorkArea;
|
|
37
|
+
const nodes_1 = require("../../nodes");
|
|
38
|
+
const Expressions = __importStar(require("../../2_statements/expressions"));
|
|
39
|
+
const Basic = __importStar(require("../../types/basic"));
|
|
40
|
+
const objects_1 = require("../../../objects");
|
|
41
|
+
const _syntax_input_1 = require("../_syntax_input");
|
|
42
|
+
// byte length of a flat type in a unicode system, as a lower and an upper bound:
|
|
43
|
+
// IntegerType also stands for INT1 and INT2, and padding is left out of the lower bound
|
|
44
|
+
function bounds(type) {
|
|
45
|
+
if (type instanceof Basic.CharacterType || type instanceof Basic.NumericType) {
|
|
46
|
+
return { min: type.getLength() * 2, max: type.getLength() * 2, align: 2 };
|
|
47
|
+
}
|
|
48
|
+
else if (type instanceof Basic.DateType) {
|
|
49
|
+
return { min: 16, max: 16, align: 2 };
|
|
50
|
+
}
|
|
51
|
+
else if (type instanceof Basic.TimeType) {
|
|
52
|
+
return { min: 12, max: 12, align: 2 };
|
|
53
|
+
}
|
|
54
|
+
else if (type instanceof Basic.IntegerType) {
|
|
55
|
+
return { min: 1, max: 4, align: 4 };
|
|
56
|
+
}
|
|
57
|
+
else if (type instanceof Basic.Integer8Type || type instanceof Basic.FloatType
|
|
58
|
+
|| type instanceof Basic.DecFloat16Type || type instanceof Basic.UTCLongType) {
|
|
59
|
+
return { min: 8, max: 8, align: 8 };
|
|
60
|
+
}
|
|
61
|
+
else if (type instanceof Basic.DecFloat34Type) {
|
|
62
|
+
return { min: 16, max: 16, align: 16 };
|
|
63
|
+
}
|
|
64
|
+
else if (type instanceof Basic.PackedType || type instanceof Basic.HexType) {
|
|
65
|
+
return { min: type.getLength(), max: type.getLength(), align: 1 };
|
|
66
|
+
}
|
|
67
|
+
else if (type instanceof Basic.StructureType) {
|
|
68
|
+
let min = 0;
|
|
69
|
+
let max = 0;
|
|
70
|
+
let align = 1;
|
|
71
|
+
for (const component of type.getComponents()) {
|
|
72
|
+
const sub = bounds(component.type);
|
|
73
|
+
if (sub === undefined) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
align = Math.max(align, sub.align);
|
|
77
|
+
max = Math.ceil(max / sub.align) * sub.align + sub.max;
|
|
78
|
+
min = min + sub.min;
|
|
79
|
+
}
|
|
80
|
+
max = Math.ceil(max / align) * align;
|
|
81
|
+
return { min, max, align };
|
|
82
|
+
}
|
|
83
|
+
// deep, generic, void or unknown
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
// INSERT/MODIFY/UPDATE dbtab FROM wa: the work area must be at least as long as the table line,
|
|
87
|
+
// client field included, else the statement is a syntax error on the system
|
|
88
|
+
function checkDatabaseWorkArea(node, dbSource, sourceTypes, input) {
|
|
89
|
+
var _a;
|
|
90
|
+
if (!(dbSource instanceof objects_1.Table)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const children = node.getChildren();
|
|
94
|
+
let workArea = undefined;
|
|
95
|
+
for (let i = 0; i < children.length - 1; i++) {
|
|
96
|
+
const child = children[i];
|
|
97
|
+
if (child instanceof nodes_1.TokenNode && child.concatTokens().toUpperCase() === "FROM") {
|
|
98
|
+
const next = children[i + 1];
|
|
99
|
+
if (next instanceof nodes_1.ExpressionNode && next.get() instanceof Expressions.SQLSource) {
|
|
100
|
+
workArea = next;
|
|
101
|
+
}
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (workArea === undefined) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const source = (_a = workArea.findFirstExpression(Expressions.SimpleSource3)) !== null && _a !== void 0 ? _a : workArea.findFirstExpression(Expressions.Source);
|
|
109
|
+
if (source === undefined) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const waType = sourceTypes.get(source);
|
|
113
|
+
if (!(waType instanceof Basic.StructureType)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const tableType = dbSource.parseType(input.scope.getRegistry());
|
|
117
|
+
const waBounds = bounds(waType);
|
|
118
|
+
const tableBounds = bounds(tableType);
|
|
119
|
+
if (waBounds === undefined || tableBounds === undefined) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (waBounds.max < tableBounds.min) {
|
|
123
|
+
const message = "The work area \"" + source.concatTokens() + "\" is not long enough for table " + dbSource.getName();
|
|
124
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, source.getFirstToken(), message));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=_check_database_work_area.js.map
|
|
@@ -17,7 +17,7 @@ class AttributeName {
|
|
|
17
17
|
return context;
|
|
18
18
|
}
|
|
19
19
|
const helper = new _object_oriented_1.ObjectOriented(input.scope);
|
|
20
|
-
let ret
|
|
20
|
+
let ret;
|
|
21
21
|
if (context instanceof object_reference_type_1.ObjectReferenceType) {
|
|
22
22
|
const def = input.scope.findObjectDefinition(context.getIdentifierName());
|
|
23
23
|
if (def === undefined) {
|
|
@@ -40,7 +40,7 @@ const let_1 = require("./let");
|
|
|
40
40
|
const _syntax_input_1 = require("../_syntax_input");
|
|
41
41
|
const basic_1 = require("../../types/basic");
|
|
42
42
|
class ConvBody {
|
|
43
|
-
static runSyntax(node, input) {
|
|
43
|
+
static runSyntax(node, input, targetType) {
|
|
44
44
|
let scoped = false;
|
|
45
45
|
const l = node.findDirectExpression(Expressions.Let);
|
|
46
46
|
if (l) {
|
|
@@ -52,7 +52,7 @@ class ConvBody {
|
|
|
52
52
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
53
53
|
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
54
54
|
}
|
|
55
|
-
const sourceType = source_1.Source.runSyntax(s, input);
|
|
55
|
+
const sourceType = source_1.Source.runSyntax(s, input, targetType);
|
|
56
56
|
if (scoped === true) {
|
|
57
57
|
input.scope.pop(node.getLastToken().getEnd());
|
|
58
58
|
}
|
|
@@ -21,7 +21,7 @@ class FormParam {
|
|
|
21
21
|
if (node.findDirectTokenByText("STRUCTURE") && nameToken) {
|
|
22
22
|
// STRUCTURES typing
|
|
23
23
|
const typeName = (_a = node.findDirectExpression(expressions_1.SimpleFieldChain)) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr();
|
|
24
|
-
let type
|
|
24
|
+
let type;
|
|
25
25
|
if (typeName) {
|
|
26
26
|
type = (_b = input.scope.findType(typeName)) === null || _b === void 0 ? void 0 : _b.getType();
|
|
27
27
|
if (type === undefined) {
|
|
@@ -127,7 +127,7 @@ class MethodParameters {
|
|
|
127
127
|
}
|
|
128
128
|
checkImporting(node, input, method) {
|
|
129
129
|
for (const item of this.parameterListT(node, input)) {
|
|
130
|
-
let parameterType
|
|
130
|
+
let parameterType;
|
|
131
131
|
if (method instanceof basic_1.VoidType) {
|
|
132
132
|
parameterType = method;
|
|
133
133
|
}
|
|
@@ -164,7 +164,7 @@ class MethodParameters {
|
|
|
164
164
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
165
165
|
return;
|
|
166
166
|
}
|
|
167
|
-
let parameterType
|
|
167
|
+
let parameterType;
|
|
168
168
|
if (method instanceof basic_1.VoidType) {
|
|
169
169
|
parameterType = method;
|
|
170
170
|
}
|
|
@@ -485,9 +485,8 @@ class Select {
|
|
|
485
485
|
}
|
|
486
486
|
static findFields(node, input) {
|
|
487
487
|
var _a, _b;
|
|
488
|
-
|
|
488
|
+
const expr = node.findFirstExpression(Expressions.SQLFieldList);
|
|
489
489
|
const ret = [];
|
|
490
|
-
expr = node.findFirstExpression(Expressions.SQLFieldList);
|
|
491
490
|
if (((_a = expr === null || expr === void 0 ? void 0 : expr.getFirstChild()) === null || _a === void 0 ? void 0 : _a.get()) instanceof Expressions.Dynamic) {
|
|
492
491
|
dynamic_1.Dynamic.runSyntax(expr.getFirstChild(), input);
|
|
493
492
|
}
|
|
@@ -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) {
|