@abaplint/core 2.120.71 → 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.
Files changed (43) hide show
  1. package/build/abaplint.d.ts +10 -0
  2. package/build/src/abap/1_lexer/lexer.js +1 -1
  3. package/build/src/abap/1_lexer/lexer_stream.js +8 -0
  4. package/build/src/abap/3_structures/structures/_combi.js +61 -112
  5. package/build/src/abap/5_syntax/basic_types.js +4 -4
  6. package/build/src/abap/5_syntax/expressions/_check_database_work_area.js +127 -0
  7. package/build/src/abap/5_syntax/expressions/attribute_name.js +1 -1
  8. package/build/src/abap/5_syntax/expressions/conv_body.js +2 -2
  9. package/build/src/abap/5_syntax/expressions/field_chain.js +1 -1
  10. package/build/src/abap/5_syntax/expressions/form_param.js +1 -1
  11. package/build/src/abap/5_syntax/expressions/method_parameters.js +2 -2
  12. package/build/src/abap/5_syntax/expressions/select.js +1 -2
  13. package/build/src/abap/5_syntax/expressions/source.js +19 -3
  14. package/build/src/abap/5_syntax/statements/assign.js +15 -1
  15. package/build/src/abap/5_syntax/statements/insert_database.js +6 -3
  16. package/build/src/abap/5_syntax/statements/loop.js +1 -1
  17. package/build/src/abap/5_syntax/statements/modify_database.js +8 -4
  18. package/build/src/abap/5_syntax/statements/update_database.js +7 -3
  19. package/build/src/abap/5_syntax/statements/when_type.js +1 -1
  20. package/build/src/abap/types/class_attributes.js +1 -1
  21. package/build/src/cds/cds_lexer.js +1 -1
  22. package/build/src/lsp/help.js +2 -2
  23. package/build/src/objects/data_element.js +1 -1
  24. package/build/src/objects/table.js +1 -0
  25. package/build/src/registry.js +1 -1
  26. package/build/src/rules/align_pseudo_comments.js +1 -1
  27. package/build/src/rules/align_type_expressions.js +1 -1
  28. package/build/src/rules/change_if_to_case.js +1 -1
  29. package/build/src/rules/check_ddic.js +1 -1
  30. package/build/src/rules/class_attribute_names.js +1 -3
  31. package/build/src/rules/downport.js +122 -24
  32. package/build/src/rules/empty_structure.js +26 -0
  33. package/build/src/rules/functional_writing.js +1 -1
  34. package/build/src/rules/keyword_case.js +1 -1
  35. package/build/src/rules/local_class_naming.js +1 -1
  36. package/build/src/rules/many_parentheses.js +1 -1
  37. package/build/src/rules/obsolete_statement.js +3 -7
  38. package/build/src/rules/parser_missing_space.js +1 -2
  39. package/build/src/rules/prefer_raise_exception_new.js +2 -8
  40. package/build/src/rules/xml_consistency.js +16 -0
  41. package/build/src/utils/form_length_stats.js +1 -1
  42. package/build/src/utils/method_length_stats.js +1 -1
  43. package/package.json +1 -1
@@ -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
- && (stream.prevChar() !== CH_BACKSLASH || (stream.prevPrevChar() === CH_BACKSLASH && stream.prevChar() === CH_BACKSLASH))) {
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
- let inn = statements;
31
- let out = [];
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.run(inn, parent);
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
- if (match.matched.length < 100) {
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 === 0) {
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[0].getFirstToken().getStr().toUpperCase();
104
+ const token = statements[index].getFirstToken().getStr().toUpperCase();
111
105
  for (const i of this.map[token] || []) {
112
- const match = i.run(statements, parent);
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.run(statements, parent);
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
- const ret = this.obj.run(statements, parent);
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
- let inn = statements;
182
- let out = [];
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 (inn.length === 0) {
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.run(inn, parent);
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
- if (match.matched.length < 100) {
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.run(statements, nparent);
254
- if (ret.matched.length === 0) {
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
- if (statements.length === 0) {
285
- return {
286
- matched: [],
287
- unmatched: [],
288
- error: true,
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[0].get() instanceof this.obj) {
294
- parent.addChild(statements[0]);
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 = undefined;
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 = undefined;
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 = undefined;
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 = undefined;
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 = undefined;
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
  }
@@ -68,7 +68,7 @@ class FieldChain {
68
68
  return found.getType();
69
69
  }
70
70
  }
71
- let context = undefined;
71
+ let context;
72
72
  const children = node.getChildren();
73
73
  context = this.findTop(children[0], input, refType);
74
74
  let prev = children[0].concatTokens();
@@ -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 = undefined;
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 = undefined;
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 = undefined;
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
- let expr = undefined;
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
- this.addIfInferred(node, input, foundType);
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 = undefined;
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) {