@abaplint/core 2.120.73 → 2.120.75
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 +6 -1
- package/build/src/abap/2_statements/combi.js +143 -51
- package/build/src/abap/2_statements/expressions/method_param_optional.js +3 -1
- package/build/src/abap/5_syntax/basic_types.js +67 -23
- package/build/src/abap/5_syntax/statements/append.js +6 -0
- package/build/src/abap/types/method_definition.js +22 -0
- package/build/src/abap/types/method_parameters.js +57 -0
- package/build/src/ddic.js +1 -1
- package/build/src/objects/data_definition.js +9 -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_exclamation_escape.js +32 -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/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/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
package/build/abaplint.d.ts
CHANGED
|
@@ -1723,6 +1723,8 @@ declare class DataControl extends AbstractObject {
|
|
|
1723
1723
|
declare class DataDefinition extends AbstractObject {
|
|
1724
1724
|
private parserError;
|
|
1725
1725
|
private parsedData;
|
|
1726
|
+
private typeCache;
|
|
1727
|
+
private typeCacheData;
|
|
1726
1728
|
getType(): string;
|
|
1727
1729
|
getAllowedNaming(): {
|
|
1728
1730
|
maxLength: number;
|
|
@@ -2036,7 +2038,8 @@ declare class Domain extends AbstractObject {
|
|
|
2036
2038
|
};
|
|
2037
2039
|
getIdentifier(): Identifier | undefined;
|
|
2038
2040
|
setDirty(): void;
|
|
2039
|
-
parseType(reg: IRegistry
|
|
2041
|
+
parseType(reg: IRegistry): AbstractType;
|
|
2042
|
+
parseDomainType(reg: IRegistry, dataElement?: string, description?: string): AbstractType;
|
|
2040
2043
|
parse(): {
|
|
2041
2044
|
updated: boolean;
|
|
2042
2045
|
runtime: number;
|
|
@@ -4770,6 +4773,7 @@ declare class MethodDefinition extends Identifier implements IMethodDefinition {
|
|
|
4770
4773
|
private readonly exceptions;
|
|
4771
4774
|
private readonly className;
|
|
4772
4775
|
constructor(node: StatementNode, visibility: Visibility, input: SyntaxInput);
|
|
4776
|
+
private checkRaisingParameter;
|
|
4773
4777
|
getVisibility(): Visibility;
|
|
4774
4778
|
getClassName(): string;
|
|
4775
4779
|
isRedefinition(): boolean;
|
|
@@ -4860,6 +4864,7 @@ declare class MethodParameters_2 implements IMethodParameters {
|
|
|
4860
4864
|
private checkNameLengths;
|
|
4861
4865
|
private workaroundRAP;
|
|
4862
4866
|
private add;
|
|
4867
|
+
private checkKeywordNames;
|
|
4863
4868
|
private isPassByValue;
|
|
4864
4869
|
}
|
|
4865
4870
|
|
|
@@ -58,6 +58,9 @@ const Tokens = __importStar(require("../1_lexer/tokens"));
|
|
|
58
58
|
const nodes_1 = require("../nodes");
|
|
59
59
|
const version_1 = require("../../version");
|
|
60
60
|
const result_1 = require("./result");
|
|
61
|
+
// shared result for "nothing matched", frozen so accidental mutation throws instead of leaking between calls.
|
|
62
|
+
// Returned arrays are never mutated by callers, which allows returning shared/input arrays as is
|
|
63
|
+
const EMPTY = Object.freeze([]);
|
|
61
64
|
class Regex {
|
|
62
65
|
constructor(r) {
|
|
63
66
|
this.regexp = r;
|
|
@@ -69,17 +72,23 @@ class Regex {
|
|
|
69
72
|
return [];
|
|
70
73
|
}
|
|
71
74
|
run(r) {
|
|
72
|
-
|
|
75
|
+
let result = undefined;
|
|
73
76
|
for (const input of r) {
|
|
74
77
|
if (input.remainingLength() === 0) {
|
|
75
78
|
continue;
|
|
76
79
|
}
|
|
77
80
|
const token = input.peek();
|
|
78
81
|
if (this.regexp.test(token.getStr()) === true) {
|
|
79
|
-
|
|
82
|
+
const shifted = input.shift(new nodes_1.TokenNodeRegex(token));
|
|
83
|
+
if (result === undefined) {
|
|
84
|
+
result = [shifted];
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
result.push(shifted);
|
|
88
|
+
}
|
|
80
89
|
}
|
|
81
90
|
}
|
|
82
|
-
return result;
|
|
91
|
+
return result !== null && result !== void 0 ? result : EMPTY;
|
|
83
92
|
}
|
|
84
93
|
railroad() {
|
|
85
94
|
return "Railroad.Terminal(\"" + this.regexp.source.replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + "\")";
|
|
@@ -102,15 +111,20 @@ class Word {
|
|
|
102
111
|
return [];
|
|
103
112
|
}
|
|
104
113
|
run(r) {
|
|
105
|
-
|
|
114
|
+
let result = undefined;
|
|
106
115
|
for (const input of r) {
|
|
107
116
|
if (input.remainingLength() !== 0
|
|
108
117
|
&& input.peek().getUpperStr() === this.s) {
|
|
109
|
-
|
|
110
|
-
result
|
|
118
|
+
const shifted = input.shift(new nodes_1.TokenNode(input.peek()));
|
|
119
|
+
if (result === undefined) {
|
|
120
|
+
result = [shifted];
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
result.push(shifted);
|
|
124
|
+
}
|
|
111
125
|
}
|
|
112
126
|
}
|
|
113
|
-
return result;
|
|
127
|
+
return result !== null && result !== void 0 ? result : EMPTY;
|
|
114
128
|
}
|
|
115
129
|
railroad() {
|
|
116
130
|
return "Railroad.Terminal('\"" + this.s + "\"')";
|
|
@@ -134,14 +148,20 @@ class Token {
|
|
|
134
148
|
return [];
|
|
135
149
|
}
|
|
136
150
|
run(r) {
|
|
137
|
-
|
|
151
|
+
let result = undefined;
|
|
138
152
|
for (const input of r) {
|
|
139
153
|
if (input.remainingLength() !== 0
|
|
140
154
|
&& input.peek().constructor === this.tokenType) {
|
|
141
|
-
|
|
155
|
+
const shifted = input.shift(new nodes_1.TokenNode(input.peek()));
|
|
156
|
+
if (result === undefined) {
|
|
157
|
+
result = [shifted];
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
result.push(shifted);
|
|
161
|
+
}
|
|
142
162
|
}
|
|
143
163
|
}
|
|
144
|
-
return result;
|
|
164
|
+
return result !== null && result !== void 0 ? result : EMPTY;
|
|
145
165
|
}
|
|
146
166
|
railroad() {
|
|
147
167
|
let text = this.name;
|
|
@@ -179,9 +199,9 @@ class Vers {
|
|
|
179
199
|
if (this.also === AlsoIn.OpenABAP) {
|
|
180
200
|
return this.runnable.run(r);
|
|
181
201
|
}
|
|
182
|
-
return (0, version_1.releaseAtLeast)(version_1.Release.v702, this.release) ? this.runnable.run(r) :
|
|
202
|
+
return (0, version_1.releaseAtLeast)(version_1.Release.v702, this.release) ? this.runnable.run(r) : EMPTY;
|
|
183
203
|
}
|
|
184
|
-
return (0, version_1.releaseAtLeast)(Combi.getRelease(), this.release) ? this.runnable.run(r) :
|
|
204
|
+
return (0, version_1.releaseAtLeast)(Combi.getRelease(), this.release) ? this.runnable.run(r) : EMPTY;
|
|
185
205
|
}
|
|
186
206
|
getUsing() {
|
|
187
207
|
return this.runnable.getUsing();
|
|
@@ -229,7 +249,7 @@ class LangVers {
|
|
|
229
249
|
return this.runnable.run(r);
|
|
230
250
|
}
|
|
231
251
|
else {
|
|
232
|
-
return
|
|
252
|
+
return EMPTY;
|
|
233
253
|
}
|
|
234
254
|
}
|
|
235
255
|
railroad() {
|
|
@@ -262,7 +282,7 @@ class LangVersNot {
|
|
|
262
282
|
return this.runnable.run(r);
|
|
263
283
|
}
|
|
264
284
|
else {
|
|
265
|
-
return
|
|
285
|
+
return EMPTY;
|
|
266
286
|
}
|
|
267
287
|
}
|
|
268
288
|
railroad() {
|
|
@@ -290,6 +310,22 @@ class OptionalPriority {
|
|
|
290
310
|
return this.optional.getUsing();
|
|
291
311
|
}
|
|
292
312
|
run(r) {
|
|
313
|
+
if (r.length === 1) {
|
|
314
|
+
// single input, pass and return the input array without wrapping
|
|
315
|
+
const res = this.optional.run(r);
|
|
316
|
+
if (res.length > 1) {
|
|
317
|
+
return res;
|
|
318
|
+
}
|
|
319
|
+
else if (res.length === 0) {
|
|
320
|
+
return r;
|
|
321
|
+
}
|
|
322
|
+
else if (res[0].remainingLength() < r[0].remainingLength()) {
|
|
323
|
+
return res;
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
return r;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
293
329
|
const result = [];
|
|
294
330
|
for (const input of r) {
|
|
295
331
|
const res = this.optional.run([input]);
|
|
@@ -329,6 +365,11 @@ class Optional {
|
|
|
329
365
|
return this.optional.getUsing();
|
|
330
366
|
}
|
|
331
367
|
run(r) {
|
|
368
|
+
if (r.length === 1) {
|
|
369
|
+
// single input, pass and return the input array without wrapping
|
|
370
|
+
const res = this.optional.run(r);
|
|
371
|
+
return res.length === 0 ? r : r.concat(res);
|
|
372
|
+
}
|
|
332
373
|
const result = [];
|
|
333
374
|
for (const input of r) {
|
|
334
375
|
result.push(input);
|
|
@@ -366,14 +407,16 @@ class Star {
|
|
|
366
407
|
let result = r;
|
|
367
408
|
try {
|
|
368
409
|
let res = r;
|
|
369
|
-
let input = [];
|
|
370
410
|
for (;;) {
|
|
371
|
-
|
|
372
|
-
res = this.sta.run(input);
|
|
411
|
+
res = this.sta.run(res);
|
|
373
412
|
if (res.length === 0) {
|
|
374
413
|
break;
|
|
375
414
|
}
|
|
376
|
-
if (
|
|
415
|
+
if (result === r) {
|
|
416
|
+
// copy on first match, the input array must not be mutated
|
|
417
|
+
result = r.concat(res);
|
|
418
|
+
}
|
|
419
|
+
else if (res.length > 1000) {
|
|
377
420
|
// avoid stack overflow
|
|
378
421
|
result = result.concat(res);
|
|
379
422
|
}
|
|
@@ -515,6 +558,17 @@ class Sequence {
|
|
|
515
558
|
return this.list.reduce((a, c) => { return a.concat(c.getUsing()); }, []);
|
|
516
559
|
}
|
|
517
560
|
run(r) {
|
|
561
|
+
if (r.length === 1) {
|
|
562
|
+
// single input, pass it down without wrapping and return the last result as is
|
|
563
|
+
let temp = r;
|
|
564
|
+
for (const sequence of this.list) {
|
|
565
|
+
temp = sequence.run(temp);
|
|
566
|
+
if (temp.length === 0) {
|
|
567
|
+
return EMPTY;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
return temp;
|
|
571
|
+
}
|
|
518
572
|
let result = [];
|
|
519
573
|
for (const input of r) {
|
|
520
574
|
let temp = [input];
|
|
@@ -592,12 +646,33 @@ class Expression {
|
|
|
592
646
|
this.runnable = undefined;
|
|
593
647
|
}
|
|
594
648
|
run(r) {
|
|
595
|
-
const results = [];
|
|
596
649
|
if (this.runnable === undefined) {
|
|
597
650
|
this.runnable = this.getRunnable();
|
|
598
651
|
}
|
|
652
|
+
if (r.length === 1) {
|
|
653
|
+
// single input, pass it down without wrapping
|
|
654
|
+
const input = r[0];
|
|
655
|
+
const temp = this.runnable.run(r);
|
|
656
|
+
if (temp.length === 0) {
|
|
657
|
+
return EMPTY;
|
|
658
|
+
}
|
|
659
|
+
const results = new Array(temp.length);
|
|
660
|
+
for (let i = 0; i < temp.length; i++) {
|
|
661
|
+
const t = temp[i];
|
|
662
|
+
const consumed = input.remainingLength() - t.remainingLength();
|
|
663
|
+
results[i] = consumed > 0 ? t.wrapConsumed(consumed, new nodes_1.ExpressionNode(this)) : t;
|
|
664
|
+
}
|
|
665
|
+
return results;
|
|
666
|
+
}
|
|
667
|
+
let results = undefined;
|
|
599
668
|
for (const input of r) {
|
|
600
669
|
const temp = this.runnable.run([input]);
|
|
670
|
+
if (temp.length === 0) {
|
|
671
|
+
continue;
|
|
672
|
+
}
|
|
673
|
+
else if (results === undefined) {
|
|
674
|
+
results = [];
|
|
675
|
+
}
|
|
601
676
|
for (const t of temp) {
|
|
602
677
|
const consumed = input.remainingLength() - t.remainingLength();
|
|
603
678
|
if (consumed > 0) {
|
|
@@ -609,8 +684,7 @@ class Expression {
|
|
|
609
684
|
}
|
|
610
685
|
}
|
|
611
686
|
}
|
|
612
|
-
|
|
613
|
-
return results;
|
|
687
|
+
return results !== null && results !== void 0 ? results : EMPTY;
|
|
614
688
|
}
|
|
615
689
|
listKeywords() {
|
|
616
690
|
// do not recurse, all Expressions are evaluated only on first level
|
|
@@ -651,12 +725,16 @@ class Permutation {
|
|
|
651
725
|
return this.list.reduce((a, c) => { return a.concat(c.getUsing()); }, []);
|
|
652
726
|
}
|
|
653
727
|
run(r) {
|
|
654
|
-
|
|
655
|
-
|
|
728
|
+
let result = undefined;
|
|
729
|
+
let copy = undefined;
|
|
656
730
|
for (let index = 0; index < this.list.length; index++) {
|
|
657
731
|
const temp = this.list[index].run(r);
|
|
658
732
|
if (temp.length !== 0) {
|
|
659
733
|
// match
|
|
734
|
+
if (result === undefined || copy === undefined) {
|
|
735
|
+
result = [];
|
|
736
|
+
copy = this.list.slice();
|
|
737
|
+
}
|
|
660
738
|
result.push(...temp);
|
|
661
739
|
const left = copy;
|
|
662
740
|
left.splice(index, 1);
|
|
@@ -668,7 +746,7 @@ class Permutation {
|
|
|
668
746
|
}
|
|
669
747
|
}
|
|
670
748
|
}
|
|
671
|
-
return result;
|
|
749
|
+
return result !== null && result !== void 0 ? result : EMPTY;
|
|
672
750
|
}
|
|
673
751
|
railroad() {
|
|
674
752
|
const children = this.list.map((e) => { return e.railroad(); });
|
|
@@ -745,17 +823,31 @@ class Alternative {
|
|
|
745
823
|
return this.list.reduce((a, c) => { return a.concat(c.getUsing()); }, []);
|
|
746
824
|
}
|
|
747
825
|
run(r) {
|
|
748
|
-
|
|
826
|
+
var _a;
|
|
827
|
+
// only allocate a new array when more than one alternative matches
|
|
828
|
+
let single = undefined;
|
|
829
|
+
let result = undefined;
|
|
749
830
|
for (const sequ of this.list) {
|
|
750
831
|
const temp = sequ.run(r);
|
|
751
|
-
if (temp.length ===
|
|
752
|
-
|
|
832
|
+
if (temp.length === 0) {
|
|
833
|
+
continue;
|
|
834
|
+
}
|
|
835
|
+
else if (result !== undefined) {
|
|
836
|
+
if (temp.length === 1) {
|
|
837
|
+
result.push(temp[0]);
|
|
838
|
+
}
|
|
839
|
+
else {
|
|
840
|
+
result.push(...temp);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
else if (single !== undefined) {
|
|
844
|
+
result = single.concat(temp);
|
|
753
845
|
}
|
|
754
846
|
else {
|
|
755
|
-
|
|
847
|
+
single = temp;
|
|
756
848
|
}
|
|
757
849
|
}
|
|
758
|
-
return result;
|
|
850
|
+
return (_a = result !== null && result !== void 0 ? result : single) !== null && _a !== void 0 ? _a : EMPTY;
|
|
759
851
|
}
|
|
760
852
|
railroad() {
|
|
761
853
|
const children = this.list.map((e) => { return e.railroad(); });
|
|
@@ -806,21 +898,13 @@ class AlternativePriority {
|
|
|
806
898
|
return this.list.reduce((a, c) => { return a.concat(c.getUsing()); }, []);
|
|
807
899
|
}
|
|
808
900
|
run(r) {
|
|
809
|
-
const result = [];
|
|
810
901
|
for (const sequ of this.list) {
|
|
811
|
-
// console.log(seq.toStr());
|
|
812
902
|
const temp = sequ.run(r);
|
|
813
903
|
if (temp.length > 0) {
|
|
814
|
-
|
|
815
|
-
result.push(temp[0]);
|
|
816
|
-
}
|
|
817
|
-
else {
|
|
818
|
-
result.push(...temp);
|
|
819
|
-
}
|
|
820
|
-
break;
|
|
904
|
+
return temp;
|
|
821
905
|
}
|
|
822
906
|
}
|
|
823
|
-
return
|
|
907
|
+
return EMPTY;
|
|
824
908
|
}
|
|
825
909
|
railroad() {
|
|
826
910
|
const children = this.list.map((e) => { return e.railroad(); });
|
|
@@ -1026,18 +1110,21 @@ class StopBefore2 {
|
|
|
1026
1110
|
getUsing() { return []; }
|
|
1027
1111
|
run(r) {
|
|
1028
1112
|
var _a;
|
|
1029
|
-
|
|
1030
|
-
|
|
1113
|
+
// only copy when something is filtered out
|
|
1114
|
+
let result = undefined;
|
|
1115
|
+
for (let i = 0; i < r.length; i++) {
|
|
1116
|
+
const input = r[i];
|
|
1031
1117
|
const next = input.peek();
|
|
1032
|
-
if (next === undefined
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1118
|
+
if (next === undefined
|
|
1119
|
+
|| (next.getUpperStr() === this.t1 && ((_a = input.peekAt(1)) === null || _a === void 0 ? void 0 : _a.getUpperStr()) === this.t2)) {
|
|
1120
|
+
if (result === undefined) {
|
|
1121
|
+
result = r.slice(0, i);
|
|
1122
|
+
}
|
|
1036
1123
|
continue;
|
|
1037
1124
|
}
|
|
1038
|
-
result.push(input);
|
|
1125
|
+
result === null || result === void 0 ? void 0 : result.push(input);
|
|
1039
1126
|
}
|
|
1040
|
-
return result;
|
|
1127
|
+
return result !== null && result !== void 0 ? result : r;
|
|
1041
1128
|
}
|
|
1042
1129
|
railroad() { return "Railroad.Terminal('stopBefore(" + this.t1 + " " + this.t2 + ")')"; }
|
|
1043
1130
|
toStr() { return "stopBefore(" + this.t1 + "," + this.t2 + ")"; }
|
|
@@ -1052,15 +1139,20 @@ class StopBefore1 {
|
|
|
1052
1139
|
getUsing() { return []; }
|
|
1053
1140
|
run(r) {
|
|
1054
1141
|
var _a;
|
|
1055
|
-
|
|
1056
|
-
|
|
1142
|
+
// only copy when something is filtered out
|
|
1143
|
+
let result = undefined;
|
|
1144
|
+
for (let i = 0; i < r.length; i++) {
|
|
1145
|
+
const input = r[i];
|
|
1057
1146
|
const next = (_a = input.peek()) === null || _a === void 0 ? void 0 : _a.getUpperStr();
|
|
1058
1147
|
if (next !== undefined && this.words.includes(next)) {
|
|
1148
|
+
if (result === undefined) {
|
|
1149
|
+
result = r.slice(0, i);
|
|
1150
|
+
}
|
|
1059
1151
|
continue;
|
|
1060
1152
|
}
|
|
1061
|
-
result.push(input);
|
|
1153
|
+
result === null || result === void 0 ? void 0 : result.push(input);
|
|
1062
1154
|
}
|
|
1063
|
-
return result;
|
|
1155
|
+
return result !== null && result !== void 0 ? result : r;
|
|
1064
1156
|
}
|
|
1065
1157
|
railroad() { return "Railroad.Terminal('stopBefore(" + this.words.join("|") + ")')"; }
|
|
1066
1158
|
toStr() { return "stopBefore(" + this.words.join(",") + ")"; }
|
|
@@ -5,7 +5,9 @@ const combi_1 = require("../combi");
|
|
|
5
5
|
const _1 = require(".");
|
|
6
6
|
class MethodParamOptional extends combi_1.Expression {
|
|
7
7
|
getRunnable() {
|
|
8
|
-
|
|
8
|
+
// not optPrio, a parameter named "optional" can follow one with a DEFAULT value:
|
|
9
|
+
// "a TYPE i DEFAULT 5 optional TYPE i"
|
|
10
|
+
return (0, combi_1.seq)(_1.MethodParam, (0, combi_1.opt)("OPTIONAL"));
|
|
9
11
|
}
|
|
10
12
|
}
|
|
11
13
|
exports.MethodParamOptional = MethodParamOptional;
|
|
@@ -42,6 +42,7 @@ const Types = __importStar(require("../types/basic"));
|
|
|
42
42
|
const _scope_type_1 = require("./_scope_type");
|
|
43
43
|
const _object_oriented_1 = require("./_object_oriented");
|
|
44
44
|
const class_constant_1 = require("../types/class_constant");
|
|
45
|
+
const class_attribute_1 = require("../types/class_attribute");
|
|
45
46
|
const identifier_1 = require("../1_lexer/tokens/identifier");
|
|
46
47
|
const _reference_1 = require("./_reference");
|
|
47
48
|
const basic_1 = require("../types/basic");
|
|
@@ -892,15 +893,18 @@ class BasicTypes {
|
|
|
892
893
|
const firstName = firstToken.getStr();
|
|
893
894
|
if (firstNode.get() instanceof Expressions.Field) {
|
|
894
895
|
const found = this.input.scope.findVariable(firstName);
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
this.input.
|
|
898
|
-
return
|
|
896
|
+
if (found === undefined) {
|
|
897
|
+
const message = `"${firstName}" not found, findTop`;
|
|
898
|
+
this.input.issues.push((0, _syntax_input_1.syntaxIssue)(this.input, firstToken, message));
|
|
899
|
+
return undefined;
|
|
899
900
|
}
|
|
900
|
-
|
|
901
|
-
|
|
901
|
+
this.input.scope.addReference(firstToken, found, _reference_1.ReferenceType.DataReadReference, this.input.filename);
|
|
902
|
+
if (this.isConstant(found) === false) {
|
|
903
|
+
const message = `VALUE, ${expr.concatTokens().toLowerCase()} is not a constant`;
|
|
904
|
+
this.input.issues.push((0, _syntax_input_1.syntaxIssue)(this.input, firstToken, message));
|
|
905
|
+
return undefined;
|
|
902
906
|
}
|
|
903
|
-
return
|
|
907
|
+
return this.constantValue(expr, found.getValue());
|
|
904
908
|
}
|
|
905
909
|
else if (firstNode.get() instanceof Expressions.ClassName
|
|
906
910
|
&& firstName.toLowerCase() === this.input.scope.getName().toLowerCase()
|
|
@@ -909,12 +913,18 @@ class BasicTypes {
|
|
|
909
913
|
const children = expr.getChildren();
|
|
910
914
|
const token = (_a = children[2]) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
911
915
|
const found = this.input.scope.findVariable(token.getStr());
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
this.input.
|
|
915
|
-
return
|
|
916
|
+
if (found === undefined) {
|
|
917
|
+
const message = `"${token.getStr()}" not found, findTop`;
|
|
918
|
+
this.input.issues.push((0, _syntax_input_1.syntaxIssue)(this.input, token, message));
|
|
919
|
+
return undefined;
|
|
916
920
|
}
|
|
917
|
-
|
|
921
|
+
this.input.scope.addReference(firstToken, found, _reference_1.ReferenceType.DataReadReference, this.input.filename);
|
|
922
|
+
if (this.isConstant(found) === false) {
|
|
923
|
+
const message = `VALUE, ${expr.concatTokens().toLowerCase()} is not a constant`;
|
|
924
|
+
this.input.issues.push((0, _syntax_input_1.syntaxIssue)(this.input, token, message));
|
|
925
|
+
return undefined;
|
|
926
|
+
}
|
|
927
|
+
return this.constantValue(expr, found.getValue());
|
|
918
928
|
}
|
|
919
929
|
else if (firstNode.get() instanceof Expressions.ClassName) {
|
|
920
930
|
const obj = this.input.scope.findObjectDefinition(firstName);
|
|
@@ -937,24 +947,58 @@ class BasicTypes {
|
|
|
937
947
|
if (c instanceof class_constant_1.ClassConstant) {
|
|
938
948
|
this.input.scope.addReference(firstToken, obj, _reference_1.ReferenceType.ObjectOrientedReference, this.input.filename, { ooName: obj.getName() });
|
|
939
949
|
this.input.scope.addReference(token, c, _reference_1.ReferenceType.DataReadReference, this.input.filename);
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
}
|
|
950
|
+
return this.constantValue(expr, c.getValue());
|
|
951
|
+
}
|
|
952
|
+
const helper = new _object_oriented_1.ObjectOriented(this.input.scope);
|
|
953
|
+
const attribute = helper.searchAttributeName(obj, attr);
|
|
954
|
+
if (attribute) {
|
|
955
|
+
this.input.scope.addReference(firstToken, obj, _reference_1.ReferenceType.ObjectOrientedReference, this.input.filename, { ooName: obj.getName() });
|
|
956
|
+
this.input.scope.addReference(token, attribute, _reference_1.ReferenceType.DataReadReference, this.input.filename);
|
|
957
|
+
const message = `VALUE, ${expr.concatTokens().toLowerCase()} is not a constant`;
|
|
958
|
+
this.input.issues.push((0, _syntax_input_1.syntaxIssue)(this.input, token, message));
|
|
950
959
|
return undefined;
|
|
951
960
|
}
|
|
952
|
-
|
|
961
|
+
const message = `Attribute or constant "${attr}" not found in "${obj.getName()}"`;
|
|
962
|
+
this.input.issues.push((0, _syntax_input_1.syntaxIssue)(this.input, token, message));
|
|
963
|
+
return undefined;
|
|
953
964
|
}
|
|
954
965
|
else {
|
|
955
966
|
throw new Error("resolveConstantValue, unexpected structure");
|
|
956
967
|
}
|
|
957
968
|
}
|
|
969
|
+
isConstant(identifier) {
|
|
970
|
+
if (identifier instanceof class_attribute_1.ClassAttribute) {
|
|
971
|
+
return false;
|
|
972
|
+
}
|
|
973
|
+
const meta = identifier.getMeta();
|
|
974
|
+
if (meta.includes("read_only" /* IdentifierMeta.ReadOnly */) === false) {
|
|
975
|
+
return false;
|
|
976
|
+
}
|
|
977
|
+
if (meta.includes("static" /* IdentifierMeta.Static */)) {
|
|
978
|
+
return true;
|
|
979
|
+
}
|
|
980
|
+
// Built-in constants and built-in system fields share ReadOnly/BuiltIn metadata.
|
|
981
|
+
// Only the constants have a value; system fields such as SY-INDEX do not.
|
|
982
|
+
return meta.includes("built-in" /* IdentifierMeta.BuiltIn */) && identifier.getValue() !== undefined;
|
|
983
|
+
}
|
|
984
|
+
constantValue(expr, value) {
|
|
985
|
+
if (typeof value === "string") {
|
|
986
|
+
return value;
|
|
987
|
+
}
|
|
988
|
+
else if (typeof value === "object" && value !== null) {
|
|
989
|
+
let current = value;
|
|
990
|
+
for (const child of expr.getChildren().slice(1)) {
|
|
991
|
+
if (child instanceof nodes_1.ExpressionNode && child.get() instanceof Expressions.ComponentName) {
|
|
992
|
+
if (typeof current !== "object" || current === null) {
|
|
993
|
+
return undefined;
|
|
994
|
+
}
|
|
995
|
+
current = current[child.getFirstToken().getStr()];
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
return typeof current === "string" ? current : undefined;
|
|
999
|
+
}
|
|
1000
|
+
return undefined;
|
|
1001
|
+
}
|
|
958
1002
|
resolveTypeRef(chain) {
|
|
959
1003
|
var _a;
|
|
960
1004
|
if (chain === undefined) {
|
|
@@ -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)) {
|
|
@@ -39,6 +39,7 @@ const Expressions = __importStar(require("../2_statements/expressions"));
|
|
|
39
39
|
const method_parameters_1 = require("./method_parameters");
|
|
40
40
|
const _identifier_1 = require("../4_file_information/_identifier");
|
|
41
41
|
const _reference_1 = require("../5_syntax/_reference");
|
|
42
|
+
const _syntax_input_1 = require("../5_syntax/_syntax_input");
|
|
42
43
|
class MethodDefinition extends _identifier_1.Identifier {
|
|
43
44
|
// todo: final flag
|
|
44
45
|
constructor(node, visibility, input) {
|
|
@@ -80,6 +81,7 @@ class MethodDefinition extends _identifier_1.Identifier {
|
|
|
80
81
|
this.static = true;
|
|
81
82
|
}
|
|
82
83
|
this.raising = [];
|
|
84
|
+
this.checkRaisingParameter(node, input);
|
|
83
85
|
for (const r of ((_c = node.findDirectExpression(Expressions.MethodDefRaising)) === null || _c === void 0 ? void 0 : _c.findAllExpressions(Expressions.ClassName)) || []) {
|
|
84
86
|
const token = r.getFirstToken();
|
|
85
87
|
const name = token.getStr();
|
|
@@ -104,6 +106,26 @@ class MethodDefinition extends _identifier_1.Identifier {
|
|
|
104
106
|
this.visibility = visibility;
|
|
105
107
|
this.parameters = new method_parameters_1.MethodParameters(node, input, this.abstract);
|
|
106
108
|
}
|
|
109
|
+
// A system reads a parameter named RAISING as the RAISING addition, measured on 758:
|
|
110
|
+
// "IMPORTING a TYPE i raising TYPE i" fails with 'Type "TYPE" is unknown'
|
|
111
|
+
checkRaisingParameter(node, input) {
|
|
112
|
+
const raising = node.findDirectExpression(Expressions.MethodDefRaising);
|
|
113
|
+
const first = raising === null || raising === void 0 ? void 0 : raising.getChildren()[1];
|
|
114
|
+
if (raising === undefined
|
|
115
|
+
|| first === undefined
|
|
116
|
+
|| !(first.get() instanceof Expressions.ClassName)
|
|
117
|
+
|| ["TYPE", "LIKE"].includes(first.getFirstToken().getStr().toUpperCase()) === false) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (node.findDirectExpression(Expressions.MethodDefImporting) === undefined
|
|
121
|
+
&& node.findDirectExpression(Expressions.MethodDefExporting) === undefined
|
|
122
|
+
&& node.findDirectExpression(Expressions.MethodDefChanging) === undefined) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const token = raising.getFirstToken();
|
|
126
|
+
const message = "Parameter \"" + token.getStr() + "\" is read as the RAISING addition, rename it or escape it as !" + token.getStr();
|
|
127
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, token, message));
|
|
128
|
+
}
|
|
107
129
|
getVisibility() {
|
|
108
130
|
return this.visibility;
|
|
109
131
|
}
|