@abaplint/core 2.110.8 → 2.111.1

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.
@@ -1378,6 +1378,7 @@ export declare class CurrentScope {
1378
1378
  addFormDefinitions(f: readonly IFormDefinition[]): void;
1379
1379
  addInterfaceDefinition(i: IInterfaceDefinition): void;
1380
1380
  addNamedIdentifier(name: string, identifier: TypedIdentifier): void;
1381
+ addNamedIdentifierToParent(name: string, identifier: TypedIdentifier): void;
1381
1382
  addIdentifier(identifier: TypedIdentifier | undefined): void;
1382
1383
  addDeferred(token: Token | undefined, type: "CLAS" | "INTF"): void;
1383
1384
  addListPrefix(identifiers: readonly TypedIdentifier[], prefix: string): void;
@@ -120,6 +120,23 @@ class CurrentScope {
120
120
  }
121
121
  this.current.getData().vars[upper] = identifier;
122
122
  }
123
+ addNamedIdentifierToParent(name, identifier) {
124
+ if (this.current === undefined) {
125
+ return;
126
+ }
127
+ const parent = this.current.getParent();
128
+ if (parent === undefined) {
129
+ return;
130
+ }
131
+ const upper = name.toUpperCase();
132
+ if (parent.getData().vars[upper] !== undefined) {
133
+ throw new Error(`Variable name "${name}" already defined`);
134
+ }
135
+ else if (this.isOO() && parent.getData().types[upper] !== undefined) {
136
+ throw new Error(`"${name}" already defined`);
137
+ }
138
+ parent.getData().vars[upper] = identifier;
139
+ }
123
140
  addIdentifier(identifier) {
124
141
  if (identifier === undefined) {
125
142
  return;
@@ -158,17 +158,18 @@ class BasicTypes {
158
158
  }
159
159
  }
160
160
  else { // field name
161
- let sub = undefined;
162
161
  if (type instanceof Types.TableType) {
163
162
  type = type.getRowType();
164
163
  }
165
164
  if (type instanceof Types.StructureType) {
166
- sub = type.getComponentByName(child.getFirstToken().getStr());
165
+ type = type.getComponentByName(child.getFirstToken().getStr());
166
+ if (type === undefined) {
167
+ return new Types.UnknownType("Type error, field not part of structure " + fullName);
168
+ }
167
169
  }
168
- if (sub === undefined) {
170
+ else if (!(type instanceof Types.VoidType)) {
169
171
  return new Types.UnknownType("Type error, field not part of structure " + fullName);
170
172
  }
171
- type = sub;
172
173
  }
173
174
  }
174
175
  if (type instanceof Types.VoidType) {
@@ -24,7 +24,7 @@ class ComponentCompareSimple {
24
24
  }
25
25
  }
26
26
  else {
27
- throw "ComponentCompareSimple, unexpected node";
27
+ throw new Error("ComponentCompareSimple, unexpected node");
28
28
  }
29
29
  }
30
30
  }
@@ -4,12 +4,18 @@ exports.Default = void 0;
4
4
  const Expressions = require("../../2_statements/expressions");
5
5
  const field_chain_1 = require("./field_chain");
6
6
  const _reference_1 = require("../_reference");
7
+ const constant_1 = require("./constant");
7
8
  class Default {
8
9
  runSyntax(node, scope, filename) {
9
10
  const chain = node.findDirectExpression(Expressions.FieldChain);
10
11
  if (chain) {
11
- new field_chain_1.FieldChain().runSyntax(chain, scope, filename, _reference_1.ReferenceType.DataReadReference);
12
+ return new field_chain_1.FieldChain().runSyntax(chain, scope, filename, _reference_1.ReferenceType.DataReadReference);
12
13
  }
14
+ const constant = node.findDirectExpression(Expressions.Constant);
15
+ if (constant) {
16
+ return new constant_1.Constant().runSyntax(constant);
17
+ }
18
+ return undefined;
13
19
  }
14
20
  }
15
21
  exports.Default = Default;
@@ -17,29 +17,25 @@ const source_field_symbol_1 = require("./source_field_symbol");
17
17
  const source_field_1 = require("./source_field");
18
18
  class FieldChain {
19
19
  runSyntax(node, scope, filename, refType) {
20
- var _a, _b, _c, _d, _e;
21
- const children = node.getChildren();
22
- let context = undefined;
23
- try {
24
- context = this.findTop(children[0], scope, filename, refType);
25
- }
26
- catch (error) {
20
+ var _a, _b, _c;
21
+ if (((_a = node.getFirstChild()) === null || _a === void 0 ? void 0 : _a.get()) instanceof Expressions.SourceField
22
+ && node.findDirectExpression(Expressions.ComponentName)) {
23
+ // workaround for names with dashes, eg. "sy-repid"
27
24
  const concat = node.concatTokens();
28
- if (concat.includes("-") && ((_a = node.getFirstChild()) === null || _a === void 0 ? void 0 : _a.get()) instanceof Expressions.SourceField) {
29
- // workaround for names with dashes, eg. "sy-repid"
30
- const offset = ((_b = node.findDirectExpression(Expressions.FieldOffset)) === null || _b === void 0 ? void 0 : _b.concatTokens()) || "";
31
- const length = ((_c = node.findDirectExpression(Expressions.FieldLength)) === null || _c === void 0 ? void 0 : _c.concatTokens()) || "";
32
- const found = scope.findVariable(concat.replace(offset, "").replace(length, ""));
33
- if (found) {
34
- if (refType) {
35
- scope.addReference(node.getFirstToken(), found, refType, filename);
36
- }
37
- // this is not completely correct, but will work, dashes in names is a mess anyhow
38
- return found.getType();
25
+ const offset = ((_b = node.findDirectExpression(Expressions.FieldOffset)) === null || _b === void 0 ? void 0 : _b.concatTokens()) || "";
26
+ const length = ((_c = node.findDirectExpression(Expressions.FieldLength)) === null || _c === void 0 ? void 0 : _c.concatTokens()) || "";
27
+ const found = scope.findVariable(concat.replace(offset, "").replace(length, ""));
28
+ if (found) {
29
+ if (refType) {
30
+ scope.addReference(node.getFirstToken(), found, refType, filename);
39
31
  }
32
+ // this is not completely correct, but will work, dashes in names is a mess anyhow
33
+ return found.getType();
40
34
  }
41
- throw error;
42
35
  }
36
+ let context = undefined;
37
+ const children = node.getChildren();
38
+ context = this.findTop(children[0], scope, filename, refType);
43
39
  for (let i = 1; i < children.length; i++) {
44
40
  const current = children[i];
45
41
  if (current === undefined) {
@@ -90,30 +86,7 @@ class FieldChain {
90
86
  if (context instanceof basic_1.TableType && context.isWithHeader()) {
91
87
  context = context.getRowType();
92
88
  }
93
- try {
94
- context = new component_name_1.ComponentName().runSyntax(context, current);
95
- }
96
- catch (error) {
97
- const concat = node.concatTokens();
98
- if (concat.includes("-")) {
99
- // workaround for names with dashes, eg. "sy-repid"
100
- const offset = ((_d = node.findDirectExpression(Expressions.FieldOffset)) === null || _d === void 0 ? void 0 : _d.concatTokens()) || "";
101
- const length = ((_e = node.findDirectExpression(Expressions.FieldLength)) === null || _e === void 0 ? void 0 : _e.concatTokens()) || "";
102
- const found = scope.findVariable(concat.replace(offset, "").replace(length, ""));
103
- if (found) {
104
- if (refType) {
105
- scope.addReference(node.getFirstToken(), found, refType, filename);
106
- }
107
- context = found.getType();
108
- }
109
- else {
110
- throw error;
111
- }
112
- }
113
- else {
114
- throw error;
115
- }
116
- }
89
+ context = new component_name_1.ComponentName().runSyntax(context, current);
117
90
  }
118
91
  else if (current instanceof nodes_1.ExpressionNode
119
92
  && current.get() instanceof Expressions.TableExpression) {
@@ -12,10 +12,11 @@ const sql_source_1 = require("./sql_source");
12
12
  const sql_compare_1 = require("./sql_compare");
13
13
  const sql_order_by_1 = require("./sql_order_by");
14
14
  const dynamic_1 = require("./dynamic");
15
+ const _reference_1 = require("../_reference");
15
16
  const isSimple = /^\w+$/;
16
17
  class Select {
17
18
  runSyntax(node, scope, filename, skipImplicitInto = false) {
18
- var _a, _b;
19
+ var _a;
19
20
  const token = node.getFirstToken();
20
21
  const from = node.findDirectExpression(Expressions.SQLFrom);
21
22
  const dbSources = from ? new sql_from_1.SQLFrom().runSyntax(from, scope, filename) : [];
@@ -45,9 +46,15 @@ class Select {
45
46
  const fields = (_a = node.findFirstExpression(Expressions.SQLAggregation)) === null || _a === void 0 ? void 0 : _a.concatTokens();
46
47
  const c = new RegExp(/^count\(\s*\*\s*\)$/, "i");
47
48
  if (fields === undefined || c.test(fields) === false) {
48
- const name = (_b = from === null || from === void 0 ? void 0 : from.findDirectExpression(Expressions.SQLFromSource)) === null || _b === void 0 ? void 0 : _b.concatTokens();
49
- if (name && scope.findVariable(name) === undefined) {
50
- throw new Error(`Target variable ${name} not found in scope`);
49
+ const nameToken = from === null || from === void 0 ? void 0 : from.findDirectExpression(Expressions.SQLFromSource);
50
+ if (nameToken) {
51
+ const found = scope.findVariable(nameToken.concatTokens());
52
+ if (found) {
53
+ scope.addReference(nameToken.getFirstToken(), found, _reference_1.ReferenceType.DataWriteReference, filename);
54
+ }
55
+ else {
56
+ throw new Error(`Target variable ${nameToken.concatTokens()} not found in scope`);
57
+ }
51
58
  }
52
59
  }
53
60
  }
@@ -4,6 +4,7 @@ exports.Tables = void 0;
4
4
  const Expressions = require("../../2_statements/expressions");
5
5
  const _typed_identifier_1 = require("../../types/_typed_identifier");
6
6
  const unknown_type_1 = require("../../types/basic/unknown_type");
7
+ const _scope_type_1 = require("../_scope_type");
7
8
  class Tables {
8
9
  runSyntax(node, scope, filename) {
9
10
  var _a, _b;
@@ -19,7 +20,13 @@ class Tables {
19
20
  const found = (_b = scope.getDDIC()) === null || _b === void 0 ? void 0 : _b.lookupTableOrView(name);
20
21
  if (found) {
21
22
  scope.getDDICReferences().addUsing(scope.getParentObj(), { object: found.object, filename: filename, token: nameToken });
22
- scope.addIdentifier(new _typed_identifier_1.TypedIdentifier(nameToken, filename, found.type));
23
+ if (scope.getType() === _scope_type_1.ScopeType.Form || scope.getType() === _scope_type_1.ScopeType.FunctionModule) {
24
+ // hoist TABLES definitions to global scope
25
+ scope.addNamedIdentifierToParent(nameToken.getStr(), new _typed_identifier_1.TypedIdentifier(nameToken, filename, found.type));
26
+ }
27
+ else {
28
+ scope.addIdentifier(new _typed_identifier_1.TypedIdentifier(nameToken, filename, found.type));
29
+ }
23
30
  return;
24
31
  }
25
32
  // this should never happen,
@@ -67,7 +67,7 @@ class Registry {
67
67
  }
68
68
  static abaplintVersion() {
69
69
  // magic, see build script "version.sh"
70
- return "2.110.8";
70
+ return "2.111.1";
71
71
  }
72
72
  getDDICReferences() {
73
73
  return this.ddicReferences;
@@ -159,6 +159,7 @@ __exportStar(require("./superclass_final"), exports);
159
159
  __exportStar(require("./superfluous_value"), exports);
160
160
  __exportStar(require("./sy_modification"), exports);
161
161
  __exportStar(require("./tabl_enhancement_category"), exports);
162
+ __exportStar(require("./tables_declared_locally"), exports);
162
163
  __exportStar(require("./try_without_catch"), exports);
163
164
  __exportStar(require("./type_form_parameters"), exports);
164
165
  __exportStar(require("./types_naming"), exports);
@@ -26,7 +26,7 @@ class MacroNaming extends _abap_rule_1.ABAPRule {
26
26
  key: "macro_naming",
27
27
  title: "Macro naming conventions",
28
28
  shortDescription: `Allows you to enforce a pattern for macro definitions`,
29
- extendedInformation: `Use rule "avoid_use" to avoid macros alotogether.`,
29
+ extendedInformation: `Use rule "avoid_use" to avoid macros altogether.`,
30
30
  tags: [_irule_1.RuleTag.Naming, _irule_1.RuleTag.SingleFile],
31
31
  badExample: `DEFINE something.
32
32
  END-OF-DEFINITION.`,
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TablesDeclaredLocally = exports.TablesDeclaredLocallyConf = void 0;
4
+ const issue_1 = require("../issue");
5
+ const Statements = require("../abap/2_statements/statements");
6
+ const Structures = require("../abap/3_structures/structures");
7
+ const _abap_rule_1 = require("./_abap_rule");
8
+ const _basic_rule_config_1 = require("./_basic_rule_config");
9
+ const _irule_1 = require("./_irule");
10
+ class TablesDeclaredLocallyConf extends _basic_rule_config_1.BasicRuleConfig {
11
+ }
12
+ exports.TablesDeclaredLocallyConf = TablesDeclaredLocallyConf;
13
+ class TablesDeclaredLocally extends _abap_rule_1.ABAPRule {
14
+ constructor() {
15
+ super(...arguments);
16
+ this.conf = new TablesDeclaredLocallyConf();
17
+ }
18
+ getMetadata() {
19
+ return {
20
+ key: "tables_declared_locally",
21
+ title: "Check for locally declared TABLES",
22
+ shortDescription: `TABLES are always global, so declare them globally`,
23
+ extendedInformation: `https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-us/abaptables.htm`,
24
+ tags: [_irule_1.RuleTag.SingleFile],
25
+ badExample: `FORM foo.
26
+ TABLES t100.
27
+ ENDFORM.`,
28
+ goodExample: `TABLES t000.`,
29
+ };
30
+ }
31
+ getConfig() {
32
+ return this.conf;
33
+ }
34
+ setConfig(conf) {
35
+ this.conf = conf;
36
+ }
37
+ runParsed(file) {
38
+ const issues = [];
39
+ const structure = file.getStructure();
40
+ if (structure === undefined) {
41
+ return issues;
42
+ }
43
+ const procedures = structure.findAllStructuresMulti([Structures.Form, Structures.FunctionModule]);
44
+ for (const p of procedures) {
45
+ const tablesStatement = p.findFirstStatement(Statements.Tables);
46
+ if (tablesStatement) {
47
+ const message = "Declare TABLES globaly";
48
+ const issue = issue_1.Issue.atStatement(file, tablesStatement, message, this.getMetadata().key, this.conf.severity);
49
+ issues.push(issue);
50
+ }
51
+ }
52
+ return issues;
53
+ }
54
+ }
55
+ exports.TablesDeclaredLocally = TablesDeclaredLocally;
56
+ //# sourceMappingURL=tables_declared_locally.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.110.8",
3
+ "version": "2.111.1",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -50,7 +50,7 @@
50
50
  },
51
51
  "homepage": "https://abaplint.org",
52
52
  "devDependencies": {
53
- "@microsoft/api-extractor": "^7.47.0",
53
+ "@microsoft/api-extractor": "^7.47.1",
54
54
  "@types/chai": "^4.3.16",
55
55
  "@types/mocha": "^10.0.7",
56
56
  "@types/node": "^20.14.10",