@abaplint/core 2.93.97 → 2.93.99

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.
@@ -8,7 +8,7 @@ const file = new MemoryFile("abapgit.abap", fs.readFileSync("./lexer_performance
8
8
  let total = 0;
9
9
  for (let i = 0; i < 10; i++) {
10
10
  const before = Date.now();
11
- const result = Lexer.run(file);
11
+ const result = new Lexer().run(file);
12
12
  const runtime = Date.now() - before;
13
13
  console.log("Runtime: " + runtime + "ms");
14
14
  total += runtime;
@@ -5602,9 +5602,6 @@ declare class Stop implements IStatement {
5602
5602
  getMatcher(): IStatementRunnable;
5603
5603
  }
5604
5604
 
5605
- declare class String_2 extends Token {
5606
- }
5607
-
5608
5605
  declare class StringTemplate extends Expression {
5609
5606
  getRunnable(): IStatementRunnable;
5610
5607
  }
@@ -5629,6 +5626,9 @@ declare class StringTemplateSource extends Expression {
5629
5626
  getRunnable(): IStatementRunnable;
5630
5627
  }
5631
5628
 
5629
+ declare class StringToken extends Token {
5630
+ }
5631
+
5632
5632
  declare class StringType extends AbstractType {
5633
5633
  toText(): string;
5634
5634
  isGeneric(): boolean;
@@ -6017,7 +6017,7 @@ declare namespace Tokens {
6017
6017
  WStaticArrow,
6018
6018
  StaticArrowW,
6019
6019
  WStaticArrowW,
6020
- String_2 as String,
6020
+ StringToken,
6021
6021
  StringTemplate_2 as StringTemplate,
6022
6022
  StringTemplateBegin,
6023
6023
  StringTemplateEnd,
@@ -8,7 +8,7 @@ const file = new src_1.MemoryFile("abapgit.abap", fs.readFileSync("./lexer_perfo
8
8
  let total = 0;
9
9
  for (let i = 0; i < 10; i++) {
10
10
  const before = Date.now();
11
- const result = lexer_1.Lexer.run(file);
11
+ const result = new lexer_1.Lexer().run(file);
12
12
  const runtime = Date.now() - before;
13
13
  console.log("Runtime: " + runtime + "ms");
14
14
  total += runtime;
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Lexer = void 0;
4
- const Tokens = require("./tokens");
5
4
  const position_1 = require("../../position");
5
+ const tokens_1 = require("./tokens");
6
6
  var Mode;
7
7
  (function (Mode) {
8
8
  Mode[Mode["Normal"] = 0] = "Normal";
@@ -25,6 +25,15 @@ class Buffer {
25
25
  clear() {
26
26
  this.buf = "";
27
27
  }
28
+ countIsEven(char) {
29
+ let count = 0;
30
+ for (let i = 0; i < this.buf.length; i += 1) {
31
+ if (this.buf.charAt(i) === char) {
32
+ count += 1;
33
+ }
34
+ }
35
+ return count % 2 === 0;
36
+ }
28
37
  }
29
38
  class Stream {
30
39
  constructor(raw) {
@@ -52,21 +61,36 @@ class Stream {
52
61
  return this.row;
53
62
  }
54
63
  prevChar() {
64
+ if (this.offset - 1 < 0) {
65
+ return "";
66
+ }
55
67
  return this.raw.substr(this.offset - 1, 1);
56
68
  }
57
69
  prevPrevChar() {
70
+ if (this.offset - 2 < 0) {
71
+ return "";
72
+ }
58
73
  return this.raw.substr(this.offset - 2, 2);
59
74
  }
60
75
  currentChar() {
61
76
  if (this.offset < 0) {
62
77
  return "\n"; // simulate newline at start of file to handle star(*) comments
63
78
  }
79
+ else if (this.offset >= this.raw.length) {
80
+ return "";
81
+ }
64
82
  return this.raw.substr(this.offset, 1);
65
83
  }
66
84
  nextChar() {
85
+ if (this.offset + 2 > this.raw.length) {
86
+ return "";
87
+ }
67
88
  return this.raw.substr(this.offset + 1, 1);
68
89
  }
69
90
  nextNextChar() {
91
+ if (this.offset + 3 > this.raw.length) {
92
+ return this.nextChar();
93
+ }
70
94
  return this.raw.substr(this.offset + 1, 2);
71
95
  }
72
96
  getRaw() {
@@ -77,22 +101,24 @@ class Stream {
77
101
  }
78
102
  }
79
103
  class Lexer {
80
- static run(file, virtual) {
104
+ run(file, virtual) {
81
105
  this.virtual = virtual;
82
106
  this.tokens = [];
83
107
  this.m = Mode.Normal;
84
108
  this.process(file.getRaw());
85
109
  return { file, tokens: this.tokens };
86
110
  }
87
- static add() {
111
+ add() {
88
112
  const s = this.buffer.get().trim();
89
113
  if (s.length > 0) {
90
114
  const col = this.stream.getCol();
91
115
  const row = this.stream.getRow();
92
116
  let whiteBefore = false;
93
- const prev = this.stream.getRaw().substr(this.stream.getOffset() - s.length, 1);
94
- if (prev === " " || prev === "\n" || prev === "\t" || prev === ":") {
95
- whiteBefore = true;
117
+ if (this.stream.getOffset() - s.length >= 0) {
118
+ const prev = this.stream.getRaw().substr(this.stream.getOffset() - s.length, 1);
119
+ if (prev === " " || prev === "\n" || prev === "\t" || prev === ":") {
120
+ whiteBefore = true;
121
+ }
96
122
  }
97
123
  let whiteAfter = false;
98
124
  const next = this.stream.nextChar();
@@ -105,174 +131,174 @@ class Lexer {
105
131
  }
106
132
  let tok = undefined;
107
133
  if (this.m === Mode.Comment) {
108
- tok = new Tokens.Comment(pos, s);
134
+ tok = new tokens_1.Comment(pos, s);
109
135
  }
110
136
  else if (this.m === Mode.Ping || this.m === Mode.Str) {
111
- tok = new Tokens.String(pos, s);
137
+ tok = new tokens_1.StringToken(pos, s);
112
138
  }
113
139
  else if (this.m === Mode.Template) {
114
140
  const first = s.charAt(0);
115
141
  const last = s.charAt(s.length - 1);
116
142
  if (first === "|" && last === "|") {
117
- tok = new Tokens.StringTemplate(pos, s);
143
+ tok = new tokens_1.StringTemplate(pos, s);
118
144
  }
119
145
  else if (first === "|" && last === "{" && whiteAfter === true) {
120
- tok = new Tokens.StringTemplateBegin(pos, s);
146
+ tok = new tokens_1.StringTemplateBegin(pos, s);
121
147
  }
122
148
  else if (first === "}" && last === "|" && whiteBefore === true) {
123
- tok = new Tokens.StringTemplateEnd(pos, s);
149
+ tok = new tokens_1.StringTemplateEnd(pos, s);
124
150
  }
125
151
  else if (first === "}" && last === "{" && whiteAfter === true && whiteBefore === true) {
126
- tok = new Tokens.StringTemplateMiddle(pos, s);
152
+ tok = new tokens_1.StringTemplateMiddle(pos, s);
127
153
  }
128
154
  else {
129
- tok = new Tokens.Identifier(pos, s);
155
+ tok = new tokens_1.Identifier(pos, s);
130
156
  }
131
157
  }
132
- else if (s.substr(0, 2) === "##") {
133
- tok = new Tokens.Pragma(pos, s);
158
+ else if (s.length > 2 && s.substr(0, 2) === "##") {
159
+ tok = new tokens_1.Pragma(pos, s);
134
160
  }
135
161
  else if (s.length === 1) {
136
162
  if (s === "." || s === ",") {
137
- tok = new Tokens.Punctuation(pos, s);
163
+ tok = new tokens_1.Punctuation(pos, s);
138
164
  }
139
165
  else if (s === "[") {
140
- if (whiteBefore && whiteAfter) {
141
- tok = new Tokens.WBracketLeftW(pos, s);
166
+ if (whiteBefore === true && whiteAfter === true) {
167
+ tok = new tokens_1.WBracketLeftW(pos, s);
142
168
  }
143
- else if (whiteBefore) {
144
- tok = new Tokens.WBracketLeft(pos, s);
169
+ else if (whiteBefore === true) {
170
+ tok = new tokens_1.WBracketLeft(pos, s);
145
171
  }
146
- else if (whiteAfter) {
147
- tok = new Tokens.BracketLeftW(pos, s);
172
+ else if (whiteAfter === true) {
173
+ tok = new tokens_1.BracketLeftW(pos, s);
148
174
  }
149
175
  else {
150
- tok = new Tokens.BracketLeft(pos, s);
176
+ tok = new tokens_1.BracketLeft(pos, s);
151
177
  }
152
178
  }
153
179
  else if (s === "(") {
154
- if (whiteBefore && whiteAfter) {
155
- tok = new Tokens.WParenLeftW(pos, s);
180
+ if (whiteBefore === true && whiteAfter === true) {
181
+ tok = new tokens_1.WParenLeftW(pos, s);
156
182
  }
157
- else if (whiteBefore) {
158
- tok = new Tokens.WParenLeft(pos, s);
183
+ else if (whiteBefore === true) {
184
+ tok = new tokens_1.WParenLeft(pos, s);
159
185
  }
160
- else if (whiteAfter) {
161
- tok = new Tokens.ParenLeftW(pos, s);
186
+ else if (whiteAfter === true) {
187
+ tok = new tokens_1.ParenLeftW(pos, s);
162
188
  }
163
189
  else {
164
- tok = new Tokens.ParenLeft(pos, s);
190
+ tok = new tokens_1.ParenLeft(pos, s);
165
191
  }
166
192
  }
167
193
  else if (s === "]") {
168
- if (whiteBefore && whiteAfter) {
169
- tok = new Tokens.WBracketRightW(pos, s);
194
+ if (whiteBefore === true && whiteAfter === true) {
195
+ tok = new tokens_1.WBracketRightW(pos, s);
170
196
  }
171
- else if (whiteBefore) {
172
- tok = new Tokens.WBracketRight(pos, s);
197
+ else if (whiteBefore === true) {
198
+ tok = new tokens_1.WBracketRight(pos, s);
173
199
  }
174
- else if (whiteAfter) {
175
- tok = new Tokens.BracketRightW(pos, s);
200
+ else if (whiteAfter === true) {
201
+ tok = new tokens_1.BracketRightW(pos, s);
176
202
  }
177
203
  else {
178
- tok = new Tokens.BracketRight(pos, s);
204
+ tok = new tokens_1.BracketRight(pos, s);
179
205
  }
180
206
  }
181
207
  else if (s === ")") {
182
- if (whiteBefore && whiteAfter) {
183
- tok = new Tokens.WParenRightW(pos, s);
208
+ if (whiteBefore === true && whiteAfter === true) {
209
+ tok = new tokens_1.WParenRightW(pos, s);
184
210
  }
185
- else if (whiteBefore) {
186
- tok = new Tokens.WParenRight(pos, s);
211
+ else if (whiteBefore === true) {
212
+ tok = new tokens_1.WParenRight(pos, s);
187
213
  }
188
- else if (whiteAfter) {
189
- tok = new Tokens.ParenRightW(pos, s);
214
+ else if (whiteAfter === true) {
215
+ tok = new tokens_1.ParenRightW(pos, s);
190
216
  }
191
217
  else {
192
- tok = new Tokens.ParenRight(pos, s);
218
+ tok = new tokens_1.ParenRight(pos, s);
193
219
  }
194
220
  }
195
221
  else if (s === "-") {
196
- if (whiteBefore && whiteAfter) {
197
- tok = new Tokens.WDashW(pos, s);
222
+ if (whiteBefore === true && whiteAfter === true) {
223
+ tok = new tokens_1.WDashW(pos, s);
198
224
  }
199
- else if (whiteBefore) {
200
- tok = new Tokens.WDash(pos, s);
225
+ else if (whiteBefore === true) {
226
+ tok = new tokens_1.WDash(pos, s);
201
227
  }
202
- else if (whiteAfter) {
203
- tok = new Tokens.DashW(pos, s);
228
+ else if (whiteAfter === true) {
229
+ tok = new tokens_1.DashW(pos, s);
204
230
  }
205
231
  else {
206
- tok = new Tokens.Dash(pos, s);
232
+ tok = new tokens_1.Dash(pos, s);
207
233
  }
208
234
  }
209
235
  else if (s === "+") {
210
- if (whiteBefore && whiteAfter) {
211
- tok = new Tokens.WPlusW(pos, s);
236
+ if (whiteBefore === true && whiteAfter === true) {
237
+ tok = new tokens_1.WPlusW(pos, s);
212
238
  }
213
- else if (whiteBefore) {
214
- tok = new Tokens.WPlus(pos, s);
239
+ else if (whiteBefore === true) {
240
+ tok = new tokens_1.WPlus(pos, s);
215
241
  }
216
- else if (whiteAfter) {
217
- tok = new Tokens.PlusW(pos, s);
242
+ else if (whiteAfter === true) {
243
+ tok = new tokens_1.PlusW(pos, s);
218
244
  }
219
245
  else {
220
- tok = new Tokens.Plus(pos, s);
246
+ tok = new tokens_1.Plus(pos, s);
221
247
  }
222
248
  }
223
249
  else if (s === "@") {
224
- if (whiteBefore && whiteAfter) {
225
- tok = new Tokens.WAtW(pos, s);
250
+ if (whiteBefore === true && whiteAfter === true) {
251
+ tok = new tokens_1.WAtW(pos, s);
226
252
  }
227
- else if (whiteBefore) {
228
- tok = new Tokens.WAt(pos, s);
253
+ else if (whiteBefore === true) {
254
+ tok = new tokens_1.WAt(pos, s);
229
255
  }
230
- else if (whiteAfter) {
231
- tok = new Tokens.AtW(pos, s);
256
+ else if (whiteAfter === true) {
257
+ tok = new tokens_1.AtW(pos, s);
232
258
  }
233
259
  else {
234
- tok = new Tokens.At(pos, s);
260
+ tok = new tokens_1.At(pos, s);
235
261
  }
236
262
  }
237
263
  }
238
264
  else if (s.length === 2) {
239
265
  if (s === "->") {
240
- if (whiteBefore && whiteAfter) {
241
- tok = new Tokens.WInstanceArrowW(pos, s);
266
+ if (whiteBefore === true && whiteAfter === true) {
267
+ tok = new tokens_1.WInstanceArrowW(pos, s);
242
268
  }
243
- else if (whiteBefore) {
244
- tok = new Tokens.WInstanceArrow(pos, s);
269
+ else if (whiteBefore === true) {
270
+ tok = new tokens_1.WInstanceArrow(pos, s);
245
271
  }
246
- else if (whiteAfter) {
247
- tok = new Tokens.InstanceArrowW(pos, s);
272
+ else if (whiteAfter === true) {
273
+ tok = new tokens_1.InstanceArrowW(pos, s);
248
274
  }
249
275
  else {
250
- tok = new Tokens.InstanceArrow(pos, s);
276
+ tok = new tokens_1.InstanceArrow(pos, s);
251
277
  }
252
278
  }
253
279
  else if (s === "=>") {
254
- if (whiteBefore && whiteAfter) {
255
- tok = new Tokens.WStaticArrowW(pos, s);
280
+ if (whiteBefore === true && whiteAfter === true) {
281
+ tok = new tokens_1.WStaticArrowW(pos, s);
256
282
  }
257
- else if (whiteBefore) {
258
- tok = new Tokens.WStaticArrow(pos, s);
283
+ else if (whiteBefore === true) {
284
+ tok = new tokens_1.WStaticArrow(pos, s);
259
285
  }
260
- else if (whiteAfter) {
261
- tok = new Tokens.StaticArrowW(pos, s);
286
+ else if (whiteAfter === true) {
287
+ tok = new tokens_1.StaticArrowW(pos, s);
262
288
  }
263
289
  else {
264
- tok = new Tokens.StaticArrow(pos, s);
290
+ tok = new tokens_1.StaticArrow(pos, s);
265
291
  }
266
292
  }
267
293
  }
268
294
  if (tok === undefined) {
269
- tok = new Tokens.Identifier(pos, s);
295
+ tok = new tokens_1.Identifier(pos, s);
270
296
  }
271
297
  this.tokens.push(tok);
272
298
  }
273
299
  this.buffer.clear();
274
300
  }
275
- static process(raw) {
301
+ process(raw) {
276
302
  this.stream = new Stream(raw.replace(/\r/g, ""));
277
303
  this.buffer = new Buffer();
278
304
  for (;;) {
@@ -318,8 +344,8 @@ class Lexer {
318
344
  && buf.length > 1
319
345
  && current === "`"
320
346
  && aahead !== "``"
321
- && (buf.split("`").length - 1) % 2 === 0
322
- && ahead !== "`") {
347
+ && ahead !== "`"
348
+ && this.buffer.countIsEven("`")) {
323
349
  // end of ping
324
350
  this.add();
325
351
  if (ahead === `"`) {
@@ -341,8 +367,8 @@ class Lexer {
341
367
  && current === "'"
342
368
  && buf.length > 1
343
369
  && aahead !== "''"
344
- && (buf.split("'").length - 1) % 2 === 0
345
- && ahead !== "'") {
370
+ && ahead !== "'"
371
+ && this.buffer.countIsEven("'")) {
346
372
  // end of string
347
373
  this.add();
348
374
  if (ahead === "\"") {
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.StringTemplateMiddle = exports.StringTemplateEnd = exports.StringTemplateBegin = exports.StringTemplate = exports.String = void 0;
3
+ exports.StringTemplateMiddle = exports.StringTemplateEnd = exports.StringTemplateBegin = exports.StringTemplate = exports.StringToken = void 0;
4
4
  const _token_1 = require("./_token");
5
- class String extends _token_1.Token {
5
+ class StringToken extends _token_1.Token {
6
6
  }
7
- exports.String = String;
7
+ exports.StringToken = StringToken;
8
8
  class StringTemplate extends _token_1.Token {
9
9
  }
10
10
  exports.StringTemplate = StringTemplate;
@@ -133,7 +133,7 @@ class ExpandMacros {
133
133
  i++;
134
134
  }
135
135
  const file = new memory_file_1.MemoryFile("expand_macros.abap.prog", str);
136
- const lexerResult = lexer_1.Lexer.run(file, statement.getFirstToken().getStart());
136
+ const lexerResult = new lexer_1.Lexer().run(file, statement.getFirstToken().getStart());
137
137
  const result = new statement_parser_1.StatementParser(this.version, this.reg).run([lexerResult], this.macros.listMacroNames());
138
138
  return result[0].statements;
139
139
  }
@@ -10,7 +10,7 @@ class Compare extends combi_1.Expression {
10
10
  const val = (0, combi_1.altPrio)(_1.FieldSub, _1.Constant);
11
11
  const list = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.WParenLeft), val, (0, combi_1.plus)((0, combi_1.seq)(",", val)), (0, combi_1.tok)(tokens_1.ParenRightW));
12
12
  const inn = (0, combi_1.seq)((0, combi_1.optPrio)("NOT"), "IN", (0, combi_1.altPrio)(_1.Source, list));
13
- const sopt = (0, combi_1.seq)("IS", (0, combi_1.optPrio)("NOT"), (0, combi_1.altPrio)("SUPPLIED", "BOUND", (0, combi_1.ver)(version_1.Version.v750, (0, combi_1.seq)("INSTANCE OF", _1.ClassName)), "REQUESTED", "INITIAL"));
13
+ const sopt = (0, combi_1.seq)("IS", (0, combi_1.optPrio)("NOT"), (0, combi_1.altPrio)("SUPPLIED", "BOUND", (0, combi_1.ver)(version_1.Version.v750, (0, combi_1.seq)("INSTANCE OF", _1.ClassName), version_1.Version.OpenABAP), "REQUESTED", "INITIAL"));
14
14
  const between = (0, combi_1.seq)((0, combi_1.optPrio)("NOT"), "BETWEEN", _1.Source, "AND", _1.Source);
15
15
  const predicate = (0, combi_1.ver)(version_1.Version.v740sp08, _1.MethodCallChain);
16
16
  const rett = (0, combi_1.seq)(_1.Source, (0, combi_1.altPrio)((0, combi_1.seq)(_1.CompareOperator, _1.Source), inn, between, sopt));
@@ -10,7 +10,7 @@ class SQLIn extends combi_1.Expression {
10
10
  const val = new _1.SQLSource();
11
11
  const short = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.At), _1.SimpleSource3);
12
12
  const listOld = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.WParenLeft), (0, combi_1.alt)((0, combi_1.ver)(version_1.Version.v740sp05, short), val), (0, combi_1.starPrio)((0, combi_1.seq)(",", val)), (0, combi_1.altPrio)((0, combi_1.tok)(tokens_1.ParenRight), (0, combi_1.tok)(tokens_1.ParenRightW), (0, combi_1.tok)(tokens_1.WParenRightW)));
13
- const listNew = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.WParenLeftW), val, (0, combi_1.starPrio)((0, combi_1.seq)(",", val)), (0, combi_1.altPrio)((0, combi_1.tok)(tokens_1.WParenRight), (0, combi_1.tok)(tokens_1.WParenRightW)));
13
+ const listNew = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.WParenLeftW), val, (0, combi_1.starPrio)((0, combi_1.seq)(",", (0, combi_1.altPrio)(short, val))), (0, combi_1.altPrio)((0, combi_1.tok)(tokens_1.WParenRight), (0, combi_1.tok)(tokens_1.WParenRightW)));
14
14
  const list = (0, combi_1.alt)(listOld, (0, combi_1.ver)(version_1.Version.v740sp02, listNew)); // version is a guess, https://github.com/abaplint/abaplint/issues/2530
15
15
  const subSelect = (0, combi_1.seq)("(", _1.Select, ")");
16
16
  const inn = (0, combi_1.seq)("IN", (0, combi_1.altPrio)(_1.SQLSource, list, subSelect));
@@ -133,7 +133,8 @@ class ABAPFileInformation {
133
133
  constants.push(...this.parseConstants(found.findFirstStructure(Structures.PrivateSection), visibility_1.Visibility.Private));
134
134
  const superClassName = (_a = found.findFirstExpression(Expressions.SuperClassName)) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr();
135
135
  const containsGlobal = found.findFirstExpression(Expressions.ClassGlobal);
136
- const concat = found.findFirstStatement(Statements.ClassDefinition).concatTokens().toUpperCase();
136
+ const cdef = found.findFirstStatement(Statements.ClassDefinition);
137
+ const concat = (cdef === null || cdef === void 0 ? void 0 : cdef.concatTokens().toUpperCase()) || "";
137
138
  this.classes.push({
138
139
  name: className.getStr(),
139
140
  identifier: new _identifier_1.Identifier(className, this.filename),
@@ -143,7 +144,7 @@ class ABAPFileInformation {
143
144
  superClassName,
144
145
  interfaces: this.getImplementing(found),
145
146
  isForTesting: concat.includes(" FOR TESTING"),
146
- isAbstract: concat.includes(" ABSTRACT"),
147
+ isAbstract: (cdef === null || cdef === void 0 ? void 0 : cdef.findDirectTokenByText("ABSTRACT")) !== undefined,
147
148
  isSharedMemory: concat.includes(" SHARED MEMORY ENABLED"),
148
149
  isFinal: found.findFirstExpression(Expressions.ClassFinal) !== undefined,
149
150
  aliases,
@@ -20,7 +20,7 @@ class ABAPParser {
20
20
  const start = Date.now();
21
21
  // 1: lexing
22
22
  const b1 = Date.now();
23
- const lexerResult = files.map(f => lexer_1.Lexer.run(f));
23
+ const lexerResult = files.map(f => new lexer_1.Lexer().run(f));
24
24
  const lexingRuntime = Date.now() - b1;
25
25
  // 2: statements
26
26
  const b2 = Date.now();
@@ -51,7 +51,7 @@ class ExpressionNode extends _abstract_node_1.AbstractNode {
51
51
  let prev;
52
52
  for (const token of this.getTokens()) {
53
53
  if (token instanceof tokens_1.Comment
54
- || token instanceof tokens_1.String
54
+ || token instanceof tokens_1.StringToken
55
55
  || token instanceof tokens_1.StringTemplate
56
56
  || token instanceof tokens_1.StringTemplateBegin
57
57
  || token instanceof tokens_1.StringTemplateMiddle
@@ -90,7 +90,7 @@ class StatementNode extends _abstract_node_1.AbstractNode {
90
90
  let prev;
91
91
  for (const token of this.getTokens()) {
92
92
  if (token instanceof comment_1.Comment
93
- || token instanceof string_1.String
93
+ || token instanceof string_1.StringToken
94
94
  || token instanceof string_1.StringTemplate
95
95
  || token instanceof string_1.StringTemplateBegin
96
96
  || token instanceof string_1.StringTemplateMiddle
@@ -226,7 +226,7 @@ class StatementNode extends _abstract_node_1.AbstractNode {
226
226
  let prev;
227
227
  for (const token of this.getTokens()) {
228
228
  if (token instanceof comment_1.Comment
229
- || token instanceof string_1.String
229
+ || token instanceof string_1.StringToken
230
230
  || token instanceof string_1.StringTemplate
231
231
  || token instanceof string_1.StringTemplateBegin
232
232
  || token instanceof string_1.StringTemplateMiddle
@@ -41,10 +41,11 @@ class ClassDefinition extends _identifier_1.Identifier {
41
41
  }
42
42
  this.methodDefs = new method_definitions_1.MethodDefinitions(this.node, this.filename, scope);
43
43
  scope.pop(node.getLastToken().getEnd());
44
- const concat = this.node.findFirstStatement(Statements.ClassDefinition).concatTokens().toUpperCase();
44
+ const cdef = this.node.findFirstStatement(Statements.ClassDefinition);
45
+ const concat = cdef.concatTokens().toUpperCase();
45
46
  this.testing = concat.includes(" FOR TESTING");
46
47
  this.sharedMemory = concat.includes(" SHARED MEMORY ENABLED");
47
- this.abstract = concat.includes(" ABSTRACT");
48
+ this.abstract = (cdef === null || cdef === void 0 ? void 0 : cdef.findDirectTokenByText("ABSTRACT")) !== undefined;
48
49
  }
49
50
  getFriends() {
50
51
  return this.friends;
@@ -9,9 +9,10 @@ class AbstractFile {
9
9
  return this.filename;
10
10
  }
11
11
  baseName() {
12
- const base1 = this.getFilename().split("\\").reverse()[0];
13
- const base2 = base1.split("/").reverse()[0];
14
- return base2;
12
+ const first = this.getFilename().split("\\");
13
+ const base1 = first[first.length - 1];
14
+ const base2 = base1.split("/");
15
+ return base2[base2.length - 1];
15
16
  }
16
17
  getObjectType() {
17
18
  var _a;
@@ -36,7 +36,7 @@ class Hover {
36
36
  if (lookup === null || lookup === void 0 ? void 0 : lookup.hover) {
37
37
  return { kind: LServer.MarkupKind.Markdown, value: lookup.hover };
38
38
  }
39
- if (found.token instanceof Tokens.String) {
39
+ if (found.token instanceof Tokens.StringToken) {
40
40
  return { kind: LServer.MarkupKind.Markdown, value: "String" };
41
41
  }
42
42
  return undefined;
@@ -76,7 +76,7 @@ class SemanticHighlighting {
76
76
  || statementInstance instanceof Statements.EndForm) {
77
77
  tokenType = BLOCK_ABAP;
78
78
  }
79
- else if (tokenInstance instanceof tokens_1.String
79
+ else if (tokenInstance instanceof tokens_1.StringToken
80
80
  || tokenInstance instanceof tokens_1.StringTemplate
81
81
  || tokenInstance instanceof tokens_1.StringTemplateBegin
82
82
  || tokenInstance instanceof tokens_1.StringTemplateEnd
@@ -39,7 +39,8 @@ class VirtualPosition extends Position {
39
39
  if (!(p instanceof VirtualPosition)) {
40
40
  return false;
41
41
  }
42
- return super.equals(this.virtual) && this.vrow === p.vrow && this.vcol === p.vcol;
42
+ const bar = p; // widening cast for ABAP translation
43
+ return super.equals(this.virtual) && this.vrow === bar.vrow && this.vcol === bar.vcol;
43
44
  }
44
45
  }
45
46
  exports.VirtualPosition = VirtualPosition;
@@ -16,7 +16,7 @@ class FixCase {
16
16
  for (const child of statement.getChildren()) {
17
17
  if (child instanceof nodes_1.TokenNodeRegex) {
18
18
  const token = child.get();
19
- if (token instanceof Tokens.String) {
19
+ if (token instanceof Tokens.StringToken) {
20
20
  continue;
21
21
  }
22
22
  this.replaceString(token.getStart(), this.formatNonKeyword(token.getStr()));
@@ -63,7 +63,7 @@ class Registry {
63
63
  }
64
64
  static abaplintVersion() {
65
65
  // magic, see build script "version.sh"
66
- return "2.93.97";
66
+ return "2.93.99";
67
67
  }
68
68
  getDDICReferences() {
69
69
  return this.references;
@@ -18,16 +18,35 @@ class IfInIf extends _abap_rule_1.ABAPRule {
18
18
  return {
19
19
  key: "if_in_if",
20
20
  title: "IF in IF",
21
- shortDescription: `Detects nested ifs which can be refactored to a single condition using AND.`,
22
- extendedInformation: `https://docs.abapopenchecks.org/checks/01/
21
+ shortDescription: `Detects nested ifs which can be refactored.`,
22
+ extendedInformation: `
23
+ Directly nested IFs without ELSE can be refactored to a single condition using AND.
24
+
25
+ ELSE condtions with directly nested IF refactored to ELSEIF.
26
+
27
+ https://docs.abapopenchecks.org/checks/01/
23
28
  https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#keep-the-nesting-depth-low`,
24
29
  badExample: `IF condition1.
25
30
  IF condition2.
26
31
  ...
27
32
  ENDIF.
33
+ ENDIF.
34
+
35
+ IF condition1.
36
+ ...
37
+ ELSE.
38
+ IF condition2.
39
+ ...
40
+ ENDIF.
28
41
  ENDIF.`,
29
42
  goodExample: `IF ( condition1 ) AND ( condition2 ).
30
43
  ...
44
+ ENDIF.
45
+
46
+ IF condition1.
47
+ ...
48
+ ELSEIF condition2.
49
+ ...
31
50
  ENDIF.`,
32
51
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
33
52
  };
@@ -42,7 +42,7 @@ https://docs.abapopenchecks.org/checks/04/`,
42
42
  for (let rowIndex = 0; rowIndex < array.length; rowIndex++) {
43
43
  const row = array[rowIndex].replace("\r", "");
44
44
  if (row.length > maxLineLength) {
45
- const message = `Maximum allowed line length of ${maxLineLength} exceeded, currently ${row.length}`;
45
+ const message = `Maximum allowed line length of ${maxLineLength} exceeded, currently ${row.length}`;
46
46
  issues.push(issue_1.Issue.atRow(file, rowIndex + 1, message, this.getMetadata().key, this.conf.severity));
47
47
  }
48
48
  else if (row.length > this.conf.length) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.93.97",
3
+ "version": "2.93.99",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",