@abaplint/core 2.119.60 → 2.119.62

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.
@@ -412,6 +412,8 @@ declare class Attributes implements IAttributes {
412
412
  private readonly filename;
413
413
  private readonly aliases;
414
414
  private readonly declaredInterfaces;
415
+ private readonly all;
416
+ private readonly byName;
415
417
  constructor(node: StructureNode, input: SyntaxInput);
416
418
  getTypes(): TypeDefinitions;
417
419
  getStatic(): ClassAttribute[];
@@ -423,6 +425,7 @@ declare class Attributes implements IAttributes {
423
425
  getConstants(): ClassConstant[];
424
426
  getConstantsByVisibility(visibility: Visibility): ClassConstant[];
425
427
  findByName(name: string): ClassAttribute | ClassConstant | undefined;
428
+ private buildByName;
426
429
  private parse;
427
430
  private parseSection;
428
431
  private parseAlias;
@@ -4398,13 +4401,16 @@ declare interface ISyntaxResult {
4398
4401
  declare interface ISyntaxSettings {
4399
4402
  /** ABAP language version */
4400
4403
  version?: VersionOldOrNew;
4401
- languageVersion?: LanguageVersion;
4402
4404
  /** Report error for objects in this regex namespace. Types not in namespace will be void. Case insensitive */
4403
4405
  errorNamespace: string;
4404
4406
  /** List of full named global constants (regex not possible)
4405
4407
  * @uniqueItems true
4406
4408
  */
4407
4409
  globalConstants?: string[];
4410
+ /** List of names to void in ambigious statements (regex not possible)
4411
+ * @uniqueItems true
4412
+ */
4413
+ ambigiousVoids?: string[];
4408
4414
  /** List of full named global macros (regex not possible)
4409
4415
  * @uniqueItems true
4410
4416
  */
@@ -6403,10 +6409,13 @@ declare class Result {
6403
6409
  private readonly tokens;
6404
6410
  private readonly tokenIndex;
6405
6411
  private nodes;
6412
+ private nodeCount;
6406
6413
  constructor(tokens: readonly Token[], tokenIndex: number, nodes?: (ExpressionNode | TokenNode)[]);
6414
+ private static fromChain;
6407
6415
  peek(): Token;
6408
6416
  peekAt(offset: number): Token | undefined;
6409
6417
  shift(node: ExpressionNode | TokenNode): Result;
6418
+ wrapConsumed(consumedTokens: number, node: ExpressionNode): Result;
6410
6419
  popNode(): ExpressionNode | TokenNode | undefined;
6411
6420
  getNodes(): (ExpressionNode | TokenNode)[];
6412
6421
  setNodes(n: (ExpressionNode | TokenNode)[]): void;
@@ -6752,6 +6761,7 @@ declare class Skip implements IStatement {
6752
6761
 
6753
6762
  export declare class SkipLogic {
6754
6763
  private readonly reg;
6764
+ private includeGraph;
6755
6765
  /** TOBJ cache hashmap */
6756
6766
  private tobj;
6757
6767
  constructor(reg: IRegistry);
@@ -599,24 +599,14 @@ class Expression {
599
599
  for (const input of r) {
600
600
  const temp = this.runnable.run([input]);
601
601
  for (const t of temp) {
602
- let consumed = input.remainingLength() - t.remainingLength();
602
+ const consumed = input.remainingLength() - t.remainingLength();
603
603
  if (consumed > 0) {
604
- const originalLength = t.getNodes().length;
605
- const children = [];
606
- while (consumed > 0) {
607
- const sub = t.popNode();
608
- if (sub) {
609
- children.push(sub);
610
- consumed = consumed - sub.countTokens();
611
- }
612
- }
613
604
  const re = new nodes_1.ExpressionNode(this);
614
- re.setChildren(children.reverse());
615
- const n = t.getNodes().slice(0, originalLength - consumed);
616
- n.push(re);
617
- t.setNodes(n);
605
+ results.push(t.wrapConsumed(consumed, re));
606
+ }
607
+ else {
608
+ results.push(t);
618
609
  }
619
- results.push(t);
620
610
  }
621
611
  }
622
612
  // console.dir(results);
@@ -7,11 +7,17 @@ class Result {
7
7
  // nodes: matched tokens
8
8
  this.tokens = tokens;
9
9
  this.tokenIndex = tokenIndex;
10
- this.nodes = nodes;
11
- if (this.nodes === undefined) {
12
- this.nodes = [];
10
+ this.nodeCount = 0;
11
+ if (nodes !== undefined) {
12
+ this.setNodes(nodes);
13
13
  }
14
14
  }
15
+ static fromChain(tokens, tokenIndex, nodes, nodeCount) {
16
+ const ret = new Result(tokens, tokenIndex);
17
+ ret.nodes = nodes;
18
+ ret.nodeCount = nodeCount;
19
+ return ret;
20
+ }
15
21
  peek() {
16
22
  return this.tokens[this.tokenIndex];
17
23
  }
@@ -19,18 +25,54 @@ class Result {
19
25
  return this.tokens[this.tokenIndex + offset];
20
26
  }
21
27
  shift(node) {
22
- const cp = this.nodes.slice();
23
- cp.push(node);
24
- return new Result(this.tokens, this.tokenIndex + 1, cp);
28
+ return Result.fromChain(this.tokens, this.tokenIndex + 1, { node, previous: this.nodes }, this.nodeCount + 1);
29
+ }
30
+ wrapConsumed(consumedTokens, node) {
31
+ let current = this.nodes;
32
+ let currentCount = this.nodeCount;
33
+ const children = [];
34
+ while (consumedTokens > 0) {
35
+ if (current === undefined) {
36
+ break;
37
+ }
38
+ children.push(current.node);
39
+ consumedTokens = consumedTokens - current.node.countTokens();
40
+ current = current.previous;
41
+ currentCount--;
42
+ }
43
+ node.setChildren(children.reverse());
44
+ this.nodes = { node, previous: current };
45
+ this.nodeCount = currentCount + 1;
46
+ return this;
25
47
  }
26
48
  popNode() {
27
- return this.nodes.pop();
49
+ if (this.nodes === undefined) {
50
+ return undefined;
51
+ }
52
+ const ret = this.nodes.node;
53
+ this.nodes = this.nodes.previous;
54
+ this.nodeCount--;
55
+ return ret;
28
56
  }
29
57
  getNodes() {
30
- return this.nodes;
58
+ const ret = new Array(this.nodeCount);
59
+ let current = this.nodes;
60
+ for (let index = this.nodeCount - 1; index >= 0; index--) {
61
+ if (current === undefined) {
62
+ break;
63
+ }
64
+ ret[index] = current.node;
65
+ current = current.previous;
66
+ }
67
+ return ret;
31
68
  }
32
69
  setNodes(n) {
33
- this.nodes = n;
70
+ this.nodes = undefined;
71
+ this.nodeCount = 0;
72
+ for (const node of n) {
73
+ this.nodes = { node, previous: this.nodes };
74
+ this.nodeCount++;
75
+ }
34
76
  }
35
77
  getTokens() {
36
78
  return this.tokens;
@@ -239,7 +239,9 @@ class StatementParser {
239
239
  statement = input;
240
240
  }
241
241
  else if (length === 1 && lastToken instanceof tokens_1.Pragma) {
242
- statement = new nodes_1.StatementNode(new _statement_1.Empty(), undefined, [lastToken]);
242
+ // special case, everything crashes if StatementNodes doesnt have children
243
+ statement = new nodes_1.StatementNode(new _statement_1.Empty(), undefined, [lastToken])
244
+ .setChildren(this.tokensToNodes([lastToken]));
243
245
  }
244
246
  }
245
247
  return statement;
@@ -296,7 +296,7 @@ class CurrentScope {
296
296
  }
297
297
  findTypePoolConstant(name) {
298
298
  var _a;
299
- if (name === undefined || name.includes("_") === undefined) {
299
+ if (name === undefined || name.includes("_") === false) {
300
300
  return undefined;
301
301
  }
302
302
  const typePoolName = name.split("_")[0];
@@ -318,7 +318,7 @@ class CurrentScope {
318
318
  }
319
319
  findTypePoolType(name) {
320
320
  var _a;
321
- if (name.includes("_") === undefined) {
321
+ if (name.includes("_") === false) {
322
322
  return undefined;
323
323
  }
324
324
  const typePoolName = name.split("_")[0];
@@ -108,11 +108,9 @@ class ObjectOriented {
108
108
  findMethodInInterface(interfaceName, methodName) {
109
109
  const idef = this.scope.findInterfaceDefinition(interfaceName);
110
110
  if (idef) {
111
- const methods = idef.getMethodDefinitions().getAll();
112
- for (const method of methods) {
113
- if (method.getName().toUpperCase() === methodName.toUpperCase()) {
114
- return { method, def: idef };
115
- }
111
+ const method = idef.getMethodDefinitions().getByName(methodName);
112
+ if (method) {
113
+ return { method, def: idef };
116
114
  }
117
115
  return this.findMethodViaAlias(methodName, idef);
118
116
  }
@@ -334,17 +332,14 @@ class ObjectOriented {
334
332
  if (defs === undefined) {
335
333
  return undefined;
336
334
  }
337
- for (const method of defs.getAll()) {
338
- if (method.getName().toUpperCase() === methodName.toUpperCase()) {
339
- if (method.isRedefinition()) {
340
- return this.findMethodInSuper(def, methodName);
341
- }
342
- else {
343
- return method;
344
- }
345
- }
335
+ const method = defs.getByName(methodName);
336
+ if (method === undefined) {
337
+ return undefined;
346
338
  }
347
- return undefined;
339
+ if (method.isRedefinition()) {
340
+ return this.findMethodInSuper(def, methodName);
341
+ }
342
+ return method;
348
343
  }
349
344
  findMethodInSuper(child, methodName) {
350
345
  let sup = child.getSuperClass();
@@ -50,18 +50,25 @@ class DeleteInternal {
50
50
  let targetType = undefined;
51
51
  const target = node.findDirectExpression(Expressions.Target);
52
52
  if (target) {
53
+ const targetName = target.concatTokens();
53
54
  let tabl = undefined;
54
- const localVariable = input.scope.findVariable(target.concatTokens());
55
+ const localVariable = input.scope.findVariable(targetName);
55
56
  if (localVariable === undefined && node.getChildren().length === 5 && node.getChildren()[2].concatTokens().toUpperCase() === "FROM") {
56
57
  // it might be a database table
57
- const found = (_a = input.scope.getDDIC()) === null || _a === void 0 ? void 0 : _a.lookupTableOrView(target.concatTokens());
58
+ const found = (_a = input.scope.getDDIC()) === null || _a === void 0 ? void 0 : _a.lookupTableOrView(targetName);
58
59
  if ((found === null || found === void 0 ? void 0 : found.object) !== undefined) {
59
60
  tabl = found;
60
61
  input.scope.getDDICReferences().addUsing(input.scope.getParentObj(), { object: tabl.object });
61
62
  }
62
63
  }
63
64
  if (tabl === undefined) {
64
- targetType = target_1.Target.runSyntax(target, input);
65
+ const ambigiousVoids = input.scope.getRegistry().getConfig().getSyntaxSetttings().ambigiousVoids || [];
66
+ if (ambigiousVoids.some(name => name.toUpperCase() === targetName.toUpperCase())) {
67
+ targetType = basic_1.VoidType.get(targetName);
68
+ }
69
+ else {
70
+ targetType = target_1.Target.runSyntax(target, input);
71
+ }
65
72
  if (node.findDirectTokenByText("TABLE") === undefined
66
73
  && node.findDirectTokenByText("ADJACENT") === undefined
67
74
  && (node.findDirectTokenByText("FROM") || node.findDirectTokenByText("INDEX"))
@@ -63,6 +63,8 @@ class Attributes {
63
63
  this.tlist = [];
64
64
  this.filename = input.filename;
65
65
  this.parse(node, input);
66
+ this.all = this.static.concat(this.instance);
67
+ this.byName = this.buildByName();
66
68
  this.types = new type_definitions_1.TypeDefinitions(this.tlist);
67
69
  }
68
70
  getTypes() {
@@ -75,10 +77,7 @@ class Attributes {
75
77
  return this.aliases;
76
78
  }
77
79
  getAll() {
78
- let res = [];
79
- res = res.concat(this.static);
80
- res = res.concat(this.instance);
81
- return res;
80
+ return this.all;
82
81
  }
83
82
  getStaticsByVisibility(visibility) {
84
83
  const attributes = [];
@@ -113,27 +112,29 @@ class Attributes {
113
112
  }
114
113
  return attributes;
115
114
  }
116
- // todo, optimize
117
115
  findByName(name) {
118
- const upper = name.toUpperCase();
119
- for (const a of this.getStatic()) {
120
- if (a.getName().toUpperCase() === upper) {
121
- return a;
122
- }
116
+ return this.byName[name.toUpperCase()];
117
+ }
118
+ /////////////////////////////
119
+ buildByName() {
120
+ const ret = {};
121
+ for (const a of this.static) {
122
+ ret[a.getName().toUpperCase()] = a;
123
123
  }
124
- for (const a of this.getInstance()) {
125
- if (a.getName().toUpperCase() === upper) {
126
- return a;
124
+ for (const a of this.instance) {
125
+ const name = a.getName().toUpperCase();
126
+ if (ret[name] === undefined) {
127
+ ret[name] = a;
127
128
  }
128
129
  }
129
- for (const a of this.getConstants()) {
130
- if (a.getName().toUpperCase() === upper) {
131
- return a;
130
+ for (const a of this.constants) {
131
+ const name = a.getName().toUpperCase();
132
+ if (ret[name] === undefined) {
133
+ ret[name] = a;
132
134
  }
133
135
  }
134
- return undefined;
136
+ return ret;
135
137
  }
136
- /////////////////////////////
137
138
  parse(node, input) {
138
139
  var _a, _b;
139
140
  const cdef = node.findDirectStructure(Structures.ClassDefinition);
@@ -47,10 +47,19 @@ class Config {
47
47
  for (const rule of sorted) {
48
48
  rules[rule.getMetadata().key] = rule.getConfig();
49
49
  }
50
- const version = ver !== null && ver !== void 0 ? ver : {
51
- release: version_1.Release.Newest.name,
52
- language: langVer !== null && langVer !== void 0 ? langVer : version_1.LanguageVersion.Normal,
53
- };
50
+ const version = langVer !== undefined
51
+ ? {
52
+ release: ver === undefined || ver === version_1.Version.Cloud
53
+ ? version_1.Release.Newest.name
54
+ : typeof ver === "string"
55
+ ? (0, version_1.versionToABAPRelease)(ver).name
56
+ : ver.release,
57
+ language: langVer,
58
+ }
59
+ : ver !== null && ver !== void 0 ? ver : {
60
+ release: version_1.Release.Newest.name,
61
+ language: version_1.LanguageVersion.Normal,
62
+ };
54
63
  // defaults: dont skip anything, report everything. The user can decide to skip stuff
55
64
  // its difficult to debug errors not being reported
56
65
  const config = {
@@ -75,9 +84,9 @@ class Config {
75
84
  }],
76
85
  syntax: {
77
86
  version,
78
- languageVersion: langVer,
79
87
  errorNamespace: "^(Z|Y|LCL\_|TY\_|LIF\_)",
80
88
  globalConstants: [],
89
+ ambigiousVoids: [],
81
90
  globalMacros: [],
82
91
  },
83
92
  rules: rules,
@@ -128,6 +137,12 @@ class Config {
128
137
  // remove duplicates,
129
138
  this.config.syntax.globalConstants = [...new Set(this.config.syntax.globalConstants)];
130
139
  }
140
+ if (this.config.syntax.ambigiousVoids === undefined) {
141
+ this.config.syntax.ambigiousVoids = [];
142
+ }
143
+ else {
144
+ this.config.syntax.ambigiousVoids = [...new Set(this.config.syntax.ambigiousVoids)];
145
+ }
131
146
  if (this.config.global.skipIncludesWithoutMain === undefined) {
132
147
  this.config.global.skipIncludesWithoutMain = false;
133
148
  }
@@ -177,9 +192,6 @@ class Config {
177
192
  return v;
178
193
  }
179
194
  getLanguageVersion() {
180
- if (this.config.syntax.languageVersion !== undefined) {
181
- return this.config.syntax.languageVersion;
182
- }
183
195
  const v = this.config.syntax.version;
184
196
  if (v !== undefined && typeof v !== "string") {
185
197
  return v.language;
@@ -204,7 +216,10 @@ class Config {
204
216
  return;
205
217
  }
206
218
  if (version === version_1.Version.Cloud) {
207
- this.config.syntax.languageVersion = version_1.LanguageVersion.Cloud;
219
+ this.config.syntax.version = {
220
+ release: version_1.Release.Newest.name,
221
+ language: version_1.LanguageVersion.Cloud,
222
+ };
208
223
  }
209
224
  // OpenABAP keeps its own version identity; open-abap-ness is derived from the
210
225
  // release in getOpenABAP() rather than a separate stored flag.
@@ -75,7 +75,7 @@ class Registry {
75
75
  }
76
76
  static abaplintVersion() {
77
77
  // magic, see build script "version.js"
78
- return "2.119.60";
78
+ return "2.119.62";
79
79
  }
80
80
  getDDICReferences() {
81
81
  return this.ddicReferences;
@@ -342,6 +342,7 @@ Make sure to test the downported code, it might not always be completely correct
342
342
  const lowConfig = this.lowReg.getConfig().get();
343
343
  highConfig.syntax.errorNamespace = lowConfig.syntax.errorNamespace;
344
344
  highConfig.syntax.globalConstants = lowConfig.syntax.globalConstants;
345
+ highConfig.syntax.ambigiousVoids = lowConfig.syntax.ambigiousVoids;
345
346
  highConfig.syntax.globalMacros = lowConfig.syntax.globalMacros;
346
347
  this.highReg = new registry_1.Registry();
347
348
  for (const o of this.lowReg.getObjects()) {
@@ -39,7 +39,6 @@ const Expressions = __importStar(require("../abap/2_statements/expressions"));
39
39
  const _abap_rule_1 = require("./_abap_rule");
40
40
  const _basic_rule_config_1 = require("./_basic_rule_config");
41
41
  const issue_1 = require("../issue");
42
- const tokens_1 = require("../abap/1_lexer/tokens");
43
42
  const expressions_1 = require("../abap/2_statements/expressions");
44
43
  const _irule_1 = require("./_irule");
45
44
  class NamesNoDashConf extends _basic_rule_config_1.BasicRuleConfig {
@@ -79,32 +78,26 @@ class NamesNoDash extends _abap_rule_1.ABAPRule {
79
78
  if (obj.getType() !== "CLAS" && obj.getType() !== "INTF") {
80
79
  for (const form of struc.findAllStatements(Statements.Form)) {
81
80
  const expr = form.findFirstExpression(expressions_1.FormName);
82
- for (const token of expr.getTokens()) {
83
- if (token instanceof tokens_1.Dash || token instanceof tokens_1.DashW) {
84
- const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
85
- issues.push(issue);
86
- break;
87
- }
81
+ const token = expr === null || expr === void 0 ? void 0 : expr.findDirectTokenByText("-");
82
+ if (token) {
83
+ const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
84
+ issues.push(issue);
88
85
  }
89
86
  }
90
87
  for (const form of struc.findAllStatements(Statements.Parameter)) {
91
88
  const expr = form.findFirstExpression(Expressions.FieldSub);
92
- for (const token of expr.getTokens()) {
93
- if (token instanceof tokens_1.Dash || token instanceof tokens_1.DashW) {
94
- const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
95
- issues.push(issue);
96
- break;
97
- }
89
+ const token = expr === null || expr === void 0 ? void 0 : expr.findDirectTokenByText("-");
90
+ if (token) {
91
+ const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
92
+ issues.push(issue);
98
93
  }
99
94
  }
100
95
  for (const form of struc.findAllStatements(Statements.SelectOption)) {
101
96
  const expr = form.findFirstExpression(Expressions.FieldSub);
102
- for (const token of expr.getTokens()) {
103
- if (token instanceof tokens_1.Dash || token instanceof tokens_1.DashW) {
104
- const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
105
- issues.push(issue);
106
- break;
107
- }
97
+ const token = expr === null || expr === void 0 ? void 0 : expr.findDirectTokenByText("-");
98
+ if (token) {
99
+ const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
100
+ issues.push(issue);
108
101
  }
109
102
  }
110
103
  }
@@ -42,6 +42,7 @@ const _basic_rule_config_1 = require("./_basic_rule_config");
42
42
  const _statement_1 = require("../abap/2_statements/statements/_statement");
43
43
  const _irule_1 = require("./_irule");
44
44
  const edit_helper_1 = require("../edit_helper");
45
+ const tokens_1 = require("../abap/1_lexer/tokens");
45
46
  class UnnecessaryPragmaConf extends _basic_rule_config_1.BasicRuleConfig {
46
47
  constructor() {
47
48
  super(...arguments);
@@ -110,6 +111,17 @@ DATA: BEGIN OF blah ##NEEDED,
110
111
  for (let i = 0; i < statements.length; i++) {
111
112
  const statement = statements[i];
112
113
  const nextStatement = statements[i + 1];
114
+ if (statement.get() instanceof _statement_1.Empty
115
+ && statement.getChildren().length === 1) {
116
+ const tokens = statement.getTokens();
117
+ if (tokens.length === 1
118
+ && tokens[0] instanceof tokens_1.Pragma) {
119
+ const message = "Pragma without a statement can be removed";
120
+ const fix = edit_helper_1.EditHelper.deleteToken(file, tokens[0]);
121
+ issues.push(issue_1.Issue.atToken(file, tokens[0], message, this.getMetadata().key, this.conf.severity, fix));
122
+ continue;
123
+ }
124
+ }
113
125
  if (statement.get() instanceof Statements.EndTry) {
114
126
  noHandler = false;
115
127
  }
@@ -6,9 +6,11 @@ const include_graph_1 = require("./utils/include_graph");
6
6
  class SkipLogic {
7
7
  constructor(reg) {
8
8
  this.reg = reg;
9
+ this.includeGraph = undefined;
9
10
  this.tobj = undefined;
10
11
  }
11
12
  skip(obj) {
13
+ var _a;
12
14
  const global = this.reg.getConfig().getGlobal();
13
15
  if (global.skipGeneratedGatewayClasses === true
14
16
  && obj instanceof objects_1.Class
@@ -18,9 +20,9 @@ class SkipLogic {
18
20
  else if (global.skipIncludesWithoutMain === true
19
21
  && obj instanceof objects_1.Program
20
22
  && obj.isInclude() === true) {
21
- const ig = new include_graph_1.IncludeGraph(this.reg);
23
+ (_a = this.includeGraph) !== null && _a !== void 0 ? _a : (this.includeGraph = new include_graph_1.IncludeGraph(this.reg));
22
24
  const file = obj.getMainABAPFile();
23
- if (file && ig.listMainForInclude(file.getFilename()).length === 0) {
25
+ if (file && this.includeGraph.listMainForInclude(file.getFilename()).length === 0) {
24
26
  return true;
25
27
  }
26
28
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.119.60",
3
+ "version": "2.119.62",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",