@abaplint/core 2.120.74 → 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 +2 -1
- package/build/src/abap/2_statements/combi.js +143 -51
- package/build/src/abap/5_syntax/statements/append.js +6 -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/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
|
@@ -2038,7 +2038,8 @@ declare class Domain extends AbstractObject {
|
|
|
2038
2038
|
};
|
|
2039
2039
|
getIdentifier(): Identifier | undefined;
|
|
2040
2040
|
setDirty(): void;
|
|
2041
|
-
parseType(reg: IRegistry
|
|
2041
|
+
parseType(reg: IRegistry): AbstractType;
|
|
2042
|
+
parseDomainType(reg: IRegistry, dataElement?: string, description?: string): AbstractType;
|
|
2042
2043
|
parse(): {
|
|
2043
2044
|
updated: boolean;
|
|
2044
2045
|
runtime: number;
|
|
@@ -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(",") + ")"; }
|
|
@@ -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)) {
|
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
|
|
@@ -0,0 +1,117 @@
|
|
|
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.AbapdocLeadingAt = exports.AbapdocLeadingAtConf = 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
|
+
class AbapdocLeadingAtConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
44
|
+
}
|
|
45
|
+
exports.AbapdocLeadingAtConf = AbapdocLeadingAtConf;
|
|
46
|
+
class AbapdocLeadingAt extends _abap_rule_1.ABAPRule {
|
|
47
|
+
constructor() {
|
|
48
|
+
super(...arguments);
|
|
49
|
+
this.conf = new AbapdocLeadingAtConf();
|
|
50
|
+
}
|
|
51
|
+
getMetadata() {
|
|
52
|
+
return {
|
|
53
|
+
key: "abapdoc_leading_at",
|
|
54
|
+
title: "ABAP Doc line starting with @",
|
|
55
|
+
shortDescription: `Reports ABAP Doc lines starting with "@" which is not followed by a command.`,
|
|
56
|
+
extendedInformation: `In ABAP Doc, "@" at the start of a line introduces a command, the commands are
|
|
57
|
+
@parameter, @raising and @exception. Any other text after a leading "@", like a CDS annotation,
|
|
58
|
+
gives the syntax warning 'A command was expected after ABAP Doc symbol "@"'.
|
|
59
|
+
|
|
60
|
+
An "@" in the middle of a line is plain text and not reported.
|
|
61
|
+
|
|
62
|
+
Only checks ABAP Doc inside class definitions and interfaces.`,
|
|
63
|
+
tags: [_irule_1.RuleTag.SingleFile],
|
|
64
|
+
badExample: `CLASS zcl_foo DEFINITION PUBLIC.
|
|
65
|
+
PUBLIC SECTION.
|
|
66
|
+
"! the first of
|
|
67
|
+
"! @UI.presentationVariant sortOrder
|
|
68
|
+
DATA mv_sort_field TYPE string.
|
|
69
|
+
ENDCLASS.`,
|
|
70
|
+
goodExample: `CLASS zcl_foo DEFINITION PUBLIC.
|
|
71
|
+
PUBLIC SECTION.
|
|
72
|
+
"! the first of @UI.presentationVariant
|
|
73
|
+
"! sortOrder
|
|
74
|
+
DATA mv_sort_field TYPE string.
|
|
75
|
+
ENDCLASS.`,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
getConfig() {
|
|
79
|
+
return this.conf;
|
|
80
|
+
}
|
|
81
|
+
setConfig(conf) {
|
|
82
|
+
this.conf = conf;
|
|
83
|
+
}
|
|
84
|
+
runParsed(file) {
|
|
85
|
+
const issues = [];
|
|
86
|
+
let definition = false;
|
|
87
|
+
for (const statement of file.getStatements()) {
|
|
88
|
+
const type = statement.get();
|
|
89
|
+
if (type instanceof Statements.ClassDefinition || type instanceof Statements.Interface) {
|
|
90
|
+
definition = true;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
else if (type instanceof Statements.EndClass || type instanceof Statements.EndInterface) {
|
|
94
|
+
definition = false;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
else if (definition === false || !(type instanceof _statement_1.Comment)) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const token = statement.getFirstToken();
|
|
101
|
+
const str = token.getStr();
|
|
102
|
+
if (str.startsWith(`"!`) === false) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const text = str.substring(2).trimStart();
|
|
106
|
+
if (text.startsWith("@") === false
|
|
107
|
+
|| text.match(/^@(parameter|raising|exception)(\s|$)/i) !== null) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const message = `A command was expected after ABAP Doc symbol "@", move the "@" away from the start of the line`;
|
|
111
|
+
issues.push(issue_1.Issue.atToken(file, token, message, this.getMetadata().key, this.conf.severity));
|
|
112
|
+
}
|
|
113
|
+
return issues;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.AbapdocLeadingAt = AbapdocLeadingAt;
|
|
117
|
+
//# sourceMappingURL=abapdoc_leading_at.js.map
|