@abaplint/core 2.80.5 → 2.80.9

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.
@@ -6,9 +6,8 @@ const basic_1 = require("../../types/basic");
6
6
  const source_1 = require("./source");
7
7
  class FieldAssignment {
8
8
  runSyntax(node, scope, filename, targetType) {
9
- var _a;
10
- const name = (_a = node.findDirectExpression(Expressions.FieldSub)) === null || _a === void 0 ? void 0 : _a.concatTokens();
11
- if (name === undefined) {
9
+ const fieldSub = node.findDirectExpression(Expressions.FieldSub);
10
+ if (fieldSub === undefined) {
12
11
  throw new Error("FieldAssignment, FieldSub node not found");
13
12
  }
14
13
  const s = node.findDirectExpression(Expressions.Source);
@@ -17,10 +16,17 @@ class FieldAssignment {
17
16
  }
18
17
  let type = undefined;
19
18
  if (targetType instanceof basic_1.StructureType) {
20
- type = targetType.getComponentByName(name);
21
- if (type === undefined && targetType.containsVoid() === false) {
22
- throw new Error(`field ${name} does not exist in structure`);
19
+ let context = targetType;
20
+ for (const c of fieldSub.getChildren()) {
21
+ const text = c.concatTokens();
22
+ if (text !== "-" && context instanceof basic_1.StructureType) {
23
+ context = context.getComponentByName(text);
24
+ if (context === undefined && targetType.containsVoid() === false) {
25
+ throw new Error(`field ${text} does not exist in structure`);
26
+ }
27
+ }
23
28
  }
29
+ type = context;
24
30
  }
25
31
  else if (targetType instanceof basic_1.VoidType) {
26
32
  type = targetType;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DeleteReport = void 0;
4
+ const Expressions = require("../../2_statements/expressions");
5
+ const source_1 = require("../expressions/source");
6
+ class DeleteReport {
7
+ runSyntax(node, scope, filename) {
8
+ for (const s of node.findDirectExpressions(Expressions.Source)) {
9
+ new source_1.Source().runSyntax(s, scope, filename);
10
+ }
11
+ }
12
+ }
13
+ exports.DeleteReport = DeleteReport;
14
+ //# sourceMappingURL=delete_report.js.map
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GetCursor = void 0;
4
+ const Expressions = require("../../2_statements/expressions");
5
+ const target_1 = require("../expressions/target");
6
+ class GetCursor {
7
+ runSyntax(node, scope, filename) {
8
+ for (const t of node.findAllExpressions(Expressions.Target)) {
9
+ new target_1.Target().runSyntax(t, scope, filename);
10
+ }
11
+ }
12
+ }
13
+ exports.GetCursor = GetCursor;
14
+ //# sourceMappingURL=get_cursor.js.map
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InsertTextpool = void 0;
4
+ const Expressions = require("../../2_statements/expressions");
5
+ const source_1 = require("../expressions/source");
6
+ class InsertTextpool {
7
+ runSyntax(node, scope, filename) {
8
+ for (const s of node.findDirectExpressions(Expressions.Source)) {
9
+ new source_1.Source().runSyntax(s, scope, filename);
10
+ }
11
+ }
12
+ }
13
+ exports.InsertTextpool = InsertTextpool;
14
+ //# sourceMappingURL=insert_textpool.js.map
@@ -122,11 +122,14 @@ const set_titlebar_1 = require("./statements/set_titlebar");
122
122
  const call_transaction_1 = require("./statements/call_transaction");
123
123
  const set_handler_1 = require("./statements/set_handler");
124
124
  const wait_1 = require("./statements/wait");
125
+ const delete_report_1 = require("./statements/delete_report");
125
126
  const shift_1 = require("./statements/shift");
126
127
  const set_bit_1 = require("./statements/set_bit");
127
128
  const modify_screen_1 = require("./statements/modify_screen");
128
129
  const delete_cluster_1 = require("./statements/delete_cluster");
129
130
  const unassign_1 = require("./statements/unassign");
131
+ const insert_textpool_1 = require("./statements/insert_textpool");
132
+ const get_cursor_1 = require("./statements/get_cursor");
130
133
  // -----------------------------------
131
134
  const map = {};
132
135
  function addToMap(handler) {
@@ -146,6 +149,7 @@ if (Object.keys(map).length === 0) {
146
149
  addToMap(new move_1.Move());
147
150
  addToMap(new get_badi_1.GetBadi());
148
151
  addToMap(new call_badi_1.CallBadi());
152
+ addToMap(new get_cursor_1.GetCursor());
149
153
  addToMap(new replace_1.Replace());
150
154
  addToMap(new truncate_dataset_1.TruncateDataset());
151
155
  addToMap(new assert_1.Assert());
@@ -154,8 +158,10 @@ if (Object.keys(map).length === 0) {
154
158
  addToMap(new set_pf_status_1.SetPFStatus());
155
159
  addToMap(new set_titlebar_1.SetTitlebar());
156
160
  addToMap(new submit_1.Submit());
161
+ addToMap(new insert_textpool_1.InsertTextpool());
157
162
  addToMap(new read_table_1.ReadTable());
158
163
  addToMap(new syntax_check_1.SyntaxCheck());
164
+ addToMap(new delete_report_1.DeleteReport());
159
165
  addToMap(new import_1.Import());
160
166
  addToMap(new collect_1.Collect());
161
167
  addToMap(new export_1.Export());
@@ -76,7 +76,7 @@ class FlowGraph {
76
76
  labelloc="t";
77
77
  label="${this.label}";
78
78
  graph [fontname = "helvetica"];
79
- node [fontname = "helvetica"];
79
+ node [fontname = "helvetica", shape="box"];
80
80
  edge [fontname = "helvetica"];
81
81
  ${this.toTextEdges()}
82
82
  }`;
@@ -6,20 +6,6 @@ const Structures = require("../3_structures/structures");
6
6
  const Statements = require("../2_statements/statements");
7
7
  const Expressions = require("../2_statements/expressions");
8
8
  const flow_graph_1 = require("./flow_graph");
9
- // Levels: top, FORM, METHOD, FUNCTION-MODULE, (MODULE, AT, END-OF-*, GET, START-OF-SELECTION, TOP-OF-PAGE)
10
- //
11
- // Loop branching: LOOP, DO, WHILE,SELECT(loop), WITH, PROVIDE
12
- //
13
- // Branching: IF, CASE, CASE TYPE OF, TRY, ON, CATCH SYSTEM-EXCEPTIONS, AT
14
- //
15
- // Conditional exits: CHECK, ASSERT
16
- //
17
- // Exits: RETURN, EXIT, RAISE(not RESUMABLE), MESSAGE(type E and A?), CONTINUE, REJECT, RESUME, STOP
18
- //
19
- // Not handled? INCLUDE + malplaced macro calls
20
- /////////////////////////////////////
21
- // TODO: handling static exceptions(only static), refactor some logic from UncaughtException to common file
22
- // TODO: RAISE
23
9
  class StatementFlow {
24
10
  constructor() {
25
11
  this.counter = 0;
@@ -31,7 +17,7 @@ class StatementFlow {
31
17
  for (const f of forms) {
32
18
  const formName = "FORM " + ((_a = f.findFirstExpression(Expressions.FormName)) === null || _a === void 0 ? void 0 : _a.concatTokens());
33
19
  this.counter = 1;
34
- const graph = this.traverseBody(this.findBody(f), "end#1", undefined);
20
+ const graph = this.traverseBody(this.findBody(f), { procedureEnd: "end#1" });
35
21
  graph.setLabel(formName);
36
22
  ret.push(graph);
37
23
  }
@@ -39,7 +25,7 @@ class StatementFlow {
39
25
  for (const f of methods) {
40
26
  const methodName = "METHOD " + ((_b = f.findFirstExpression(Expressions.MethodName)) === null || _b === void 0 ? void 0 : _b.concatTokens());
41
27
  this.counter = 1;
42
- const graph = this.traverseBody(this.findBody(f), "end#1", undefined);
28
+ const graph = this.traverseBody(this.findBody(f), { procedureEnd: "end#1" });
43
29
  graph.setLabel(methodName);
44
30
  ret.push(graph);
45
31
  }
@@ -50,12 +36,27 @@ class StatementFlow {
50
36
  return ((_a = f.findDirectStructure(Structures.Body)) === null || _a === void 0 ? void 0 : _a.getChildren()) || [];
51
37
  }
52
38
  buildName(statement) {
53
- // note: there might be multiple statements on the same line
39
+ let token = undefined;
40
+ const colon = statement.getColon();
41
+ if (colon === undefined) {
42
+ token = statement.getFirstToken();
43
+ }
44
+ else {
45
+ for (const t of statement.getTokens()) {
46
+ if (t.getStart().isAfter(colon.getEnd())) {
47
+ token = t;
48
+ break;
49
+ }
50
+ }
51
+ }
52
+ if (token === undefined) {
53
+ return "tokenError";
54
+ }
54
55
  return statement.get().constructor.name +
55
- ":" + statement.getFirstToken().getRow() +
56
- "," + statement.getFirstToken().getCol();
56
+ ":" + token.getRow() +
57
+ "," + token.getCol();
57
58
  }
58
- traverseBody(children, procedureEnd, loopStart) {
59
+ traverseBody(children, context) {
59
60
  const graph = new flow_graph_1.FlowGraph(this.counter++);
60
61
  if (children.length === 0) {
61
62
  graph.addEdge(graph.getStart(), graph.getEnd());
@@ -70,37 +71,36 @@ class StatementFlow {
70
71
  graph.addEdge(current, name);
71
72
  current = name;
72
73
  if (firstChild.get() instanceof Statements.Check) {
73
- if (loopStart) {
74
- graph.addEdge(name, loopStart);
74
+ if (context.loopStart) {
75
+ graph.addEdge(name, context.loopStart);
75
76
  }
76
77
  else {
77
- graph.addEdge(name, procedureEnd);
78
+ graph.addEdge(name, context.procedureEnd);
78
79
  }
79
80
  }
80
81
  else if (firstChild.get() instanceof Statements.Assert) {
81
- graph.addEdge(name, procedureEnd);
82
+ graph.addEdge(name, context.procedureEnd);
82
83
  }
83
- else if (firstChild.get() instanceof Statements.Continue && loopStart) {
84
- graph.addEdge(name, loopStart);
84
+ else if (firstChild.get() instanceof Statements.Continue && context.loopStart) {
85
+ graph.addEdge(name, context.loopStart);
85
86
  return graph;
86
87
  }
87
88
  else if (firstChild.get() instanceof Statements.Exit) {
88
- if (loopStart) {
89
- // hmm, perhaps this should hit loop end instead?
90
- graph.addEdge(name, loopStart);
89
+ if (context.loopEnd) {
90
+ graph.addEdge(name, context.loopEnd);
91
91
  }
92
92
  else {
93
- graph.addEdge(name, procedureEnd);
93
+ graph.addEdge(name, context.procedureEnd);
94
94
  }
95
95
  return graph;
96
96
  }
97
97
  else if (firstChild.get() instanceof Statements.Return) {
98
- graph.addEdge(name, procedureEnd);
98
+ graph.addEdge(name, context.procedureEnd);
99
99
  return graph;
100
100
  }
101
101
  }
102
102
  else if (firstChild instanceof nodes_1.StructureNode) {
103
- const sub = this.traverseStructure(firstChild, procedureEnd, loopStart);
103
+ const sub = this.traverseStructure(firstChild, context);
104
104
  current = graph.addGraph(current, sub);
105
105
  }
106
106
  }
@@ -108,7 +108,7 @@ class StatementFlow {
108
108
  graph.addEdge(current, graph.getEnd());
109
109
  return graph;
110
110
  }
111
- traverseStructure(n, procedureEnd, loopStart) {
111
+ traverseStructure(n, context) {
112
112
  const graph = new flow_graph_1.FlowGraph(this.counter++);
113
113
  if (n === undefined) {
114
114
  return graph;
@@ -117,7 +117,7 @@ class StatementFlow {
117
117
  const type = n.get();
118
118
  if (type instanceof Structures.If) {
119
119
  const ifName = this.buildName(n.findDirectStatement(Statements.If));
120
- const sub = this.traverseBody(this.findBody(n), procedureEnd, loopStart);
120
+ const sub = this.traverseBody(this.findBody(n), context);
121
121
  graph.addEdge(current, ifName);
122
122
  graph.addGraph(ifName, sub);
123
123
  graph.addEdge(sub.getEnd(), graph.getEnd());
@@ -128,7 +128,7 @@ class StatementFlow {
128
128
  continue;
129
129
  }
130
130
  const elseIfName = this.buildName(elseifst);
131
- const sub = this.traverseBody(this.findBody(e), procedureEnd, loopStart);
131
+ const sub = this.traverseBody(this.findBody(e), context);
132
132
  graph.addEdge(current, elseIfName);
133
133
  graph.addGraph(elseIfName, sub);
134
134
  graph.addEdge(sub.getEnd(), graph.getEnd());
@@ -138,7 +138,7 @@ class StatementFlow {
138
138
  const elsest = els === null || els === void 0 ? void 0 : els.findDirectStatement(Statements.Else);
139
139
  if (els && elsest) {
140
140
  const elseName = this.buildName(elsest);
141
- const sub = this.traverseBody(this.findBody(els), procedureEnd, loopStart);
141
+ const sub = this.traverseBody(this.findBody(els), context);
142
142
  graph.addEdge(current, elseName);
143
143
  graph.addGraph(elseName, sub);
144
144
  graph.addEdge(sub.getEnd(), graph.getEnd());
@@ -154,7 +154,7 @@ class StatementFlow {
154
154
  || type instanceof Structures.Select
155
155
  || type instanceof Structures.Do) {
156
156
  const loopName = this.buildName(n.getFirstStatement());
157
- const sub = this.traverseBody(this.findBody(n), procedureEnd, loopName);
157
+ const sub = this.traverseBody(this.findBody(n), Object.assign(Object.assign({}, context), { loopStart: loopName, loopEnd: graph.getEnd() }));
158
158
  graph.addEdge(current, loopName);
159
159
  graph.addGraph(loopName, sub);
160
160
  graph.addEdge(sub.getEnd(), loopName);
@@ -162,13 +162,13 @@ class StatementFlow {
162
162
  }
163
163
  else if (type instanceof Structures.Try) {
164
164
  const tryName = this.buildName(n.getFirstStatement());
165
- const body = this.traverseBody(this.findBody(n), procedureEnd, loopStart);
165
+ const body = this.traverseBody(this.findBody(n), context);
166
166
  graph.addEdge(current, tryName);
167
167
  graph.addGraph(tryName, body);
168
168
  graph.addEdge(body.getEnd(), graph.getEnd());
169
169
  for (const c of n.findDirectStructures(Structures.Catch)) {
170
170
  const catchName = this.buildName(c.getFirstStatement());
171
- const catchBody = this.traverseBody(this.findBody(c), procedureEnd, loopStart);
171
+ const catchBody = this.traverseBody(this.findBody(c), context);
172
172
  // TODO: this does not take exceptions into account
173
173
  graph.addEdge(body.getEnd(), catchName);
174
174
  graph.addGraph(catchName, catchBody);
@@ -189,7 +189,7 @@ class StatementFlow {
189
189
  othersFound = true;
190
190
  }
191
191
  const firstName = this.buildName(first);
192
- const sub = this.traverseBody(this.findBody(w), procedureEnd, loopStart);
192
+ const sub = this.traverseBody(this.findBody(w), context);
193
193
  graph.addEdge(caseName, firstName);
194
194
  graph.addGraph(firstName, sub);
195
195
  graph.addEdge(sub.getEnd(), graph.getEnd());
@@ -211,7 +211,7 @@ class StatementFlow {
211
211
  othersFound = true;
212
212
  }
213
213
  const firstName = this.buildName(first);
214
- const sub = this.traverseBody(this.findBody(w), procedureEnd, loopStart);
214
+ const sub = this.traverseBody(this.findBody(w), context);
215
215
  graph.addEdge(caseName, firstName);
216
216
  graph.addGraph(firstName, sub);
217
217
  graph.addEdge(sub.getEnd(), graph.getEnd());
@@ -221,7 +221,7 @@ class StatementFlow {
221
221
  }
222
222
  }
223
223
  else {
224
- console.dir("todo, " + n.get().constructor.name);
224
+ console.dir("StatementFlow,todo, " + n.get().constructor.name);
225
225
  }
226
226
  return graph;
227
227
  }
@@ -30,12 +30,12 @@ class References {
30
30
  const locs = this.search(lookup.definitionId, lookup.scope);
31
31
  return locs.map(_lsp_utils_1.LSPUtils.identiferToLocation);
32
32
  }
33
+ // todo, cleanup this mehtod, some of the method parameters are not used anymore?
33
34
  search(identifier, node, exitAfterFound = false, removeDuplicates = true) {
34
35
  let ret = [];
35
36
  // todo, this first assumes that the identifier is a variable?
36
- if (node.getIdentifier().stype === _scope_type_1.ScopeType.Method
37
- || node.getIdentifier().stype === _scope_type_1.ScopeType.FunctionModule
38
- || node.getIdentifier().stype === _scope_type_1.ScopeType.Form) {
37
+ const stype = node.getIdentifier().stype;
38
+ if (stype === _scope_type_1.ScopeType.Method || stype === _scope_type_1.ScopeType.FunctionModule || stype === _scope_type_1.ScopeType.Form) {
39
39
  ret = this.findReferences(node, identifier);
40
40
  }
41
41
  if (ret.length > 1 && exitAfterFound === true) {
@@ -71,15 +71,16 @@ class References {
71
71
  var _a;
72
72
  const ret = [];
73
73
  if (node.getIdentifier().stype !== _scope_type_1.ScopeType.BuiltIn) {
74
+ const upper = identifier.getName().toUpperCase();
74
75
  // this is for finding the definitions
75
76
  const vars = node.getData().vars;
76
- const vid = vars[identifier.getName().toUpperCase()];
77
+ const vid = vars[upper];
77
78
  if (vid === null || vid === void 0 ? void 0 : vid.equals(identifier)) {
78
79
  ret.push(vid);
79
80
  }
80
81
  // this is for finding the definitions
81
82
  const types = node.getData().types;
82
- const tid = types[identifier.getName().toUpperCase()];
83
+ const tid = types[upper];
83
84
  if (tid === null || tid === void 0 ? void 0 : tid.equals(identifier)) {
84
85
  ret.push(tid);
85
86
  }
@@ -68,7 +68,7 @@ class Registry {
68
68
  }
69
69
  static abaplintVersion() {
70
70
  // magic, see build script "version.sh"
71
- return "2.80.5";
71
+ return "2.80.9";
72
72
  }
73
73
  getDDICReferences() {
74
74
  return this.references;
@@ -36,23 +36,25 @@ class WorkArea {
36
36
  return this.workarea.length;
37
37
  }
38
38
  }
39
- function removeDuplicates(list) {
40
- const deduplicated = [];
41
- for (const result of list) {
42
- let cont = false;
43
- for (const d of deduplicated) {
44
- if (result.getStart().equals(d.getStart())) {
45
- cont = true;
46
- break;
47
- }
48
- }
49
- if (cont === true) {
50
- continue;
51
- }
52
- deduplicated.push(result);
53
- }
54
- return deduplicated;
39
+ /*
40
+ function removeDuplicates(list: readonly TypedIdentifier[]): readonly TypedIdentifier[] {
41
+ const deduplicated: TypedIdentifier[] = [];
42
+ for (const result of list) {
43
+ let cont = false;
44
+ for (const d of deduplicated) {
45
+ if (result.getStart().equals(d.getStart())) {
46
+ cont = true;
47
+ break;
48
+ }
49
+ }
50
+ if (cont === true) {
51
+ continue;
52
+ }
53
+ deduplicated.push(result);
54
+ }
55
+ return deduplicated;
55
56
  }
57
+ */
56
58
  class UnusedTypesConf extends _basic_rule_config_1.BasicRuleConfig {
57
59
  constructor() {
58
60
  super(...arguments);
@@ -103,7 +105,10 @@ class UnusedTypes {
103
105
  return []; // exit early if all types are used in the current object
104
106
  }
105
107
  for (const o of this.reg.getObjects()) {
106
- if (o instanceof _abap_object_1.ABAPObject) {
108
+ if (o === obj) {
109
+ continue;
110
+ }
111
+ else if (o instanceof _abap_object_1.ABAPObject) {
107
112
  if (this.reg.isDependency(o)) {
108
113
  continue; // do not search in dependencies
109
114
  }
@@ -116,7 +121,7 @@ class UnusedTypes {
116
121
  }
117
122
  // what is left is unused
118
123
  const ret = [];
119
- for (const t of removeDuplicates(this.workarea.get())) {
124
+ for (const t of this.workarea.get()) {
120
125
  const message = "Type \"" + t.getName() + "\" not used";
121
126
  const file = obj.getABAPFileByName(t.getFilename());
122
127
  if (file === undefined) {
@@ -8,10 +8,10 @@ const syntax_1 = require("../abap/5_syntax/syntax");
8
8
  const _abap_object_1 = require("../objects/_abap_object");
9
9
  const _scope_type_1 = require("../abap/5_syntax/_scope_type");
10
10
  const objects_1 = require("../objects");
11
- const references_1 = require("../lsp/references");
12
11
  const edit_helper_1 = require("../edit_helper");
13
12
  const Statements = require("../abap/2_statements/statements");
14
13
  const _statement_1 = require("../abap/2_statements/statements/_statement");
14
+ const _reference_1 = require("../abap/5_syntax/_reference");
15
15
  class UnusedVariablesConf extends _basic_rule_config_1.BasicRuleConfig {
16
16
  constructor() {
17
17
  super(...arguments);
@@ -22,6 +22,39 @@ class UnusedVariablesConf extends _basic_rule_config_1.BasicRuleConfig {
22
22
  }
23
23
  }
24
24
  exports.UnusedVariablesConf = UnusedVariablesConf;
25
+ class WorkArea {
26
+ constructor() {
27
+ this.workarea = [];
28
+ }
29
+ push(id, count = 1) {
30
+ for (const w of this.workarea) {
31
+ if (id.equals(w.id)) {
32
+ return;
33
+ }
34
+ }
35
+ this.workarea.push({ id, count });
36
+ }
37
+ removeIfExists(id) {
38
+ if (id === undefined) {
39
+ return;
40
+ }
41
+ for (let i = 0; i < this.workarea.length; i++) {
42
+ if (id.equals(this.workarea[i].id)) {
43
+ this.workarea[i].count--;
44
+ if (this.workarea[i].count === 0) {
45
+ this.workarea.splice(i, 1);
46
+ }
47
+ return;
48
+ }
49
+ }
50
+ }
51
+ get() {
52
+ return this.workarea;
53
+ }
54
+ count() {
55
+ return this.workarea.length;
56
+ }
57
+ }
25
58
  class UnusedVariables {
26
59
  constructor() {
27
60
  this.conf = new UnusedVariablesConf();
@@ -33,11 +66,11 @@ class UnusedVariables {
33
66
  shortDescription: `Checks for unused variables and constants`,
34
67
  extendedInformation: `WARNING: slow
35
68
 
36
- Experimental, might give false positives. Skips event parameters.
69
+ Experimental, might give false positives. Skips event parameters.
37
70
 
38
- Note that this currently does not work if the source code uses macros.
71
+ Note that this currently does not work if the source code uses macros.
39
72
 
40
- Unused variables are not reported if the object contains syntax errors.`,
73
+ Unused variables are not reported if the object contains syntax errors. Errors found in INCLUDES are reported for the main program.`,
41
74
  tags: [_irule_1.RuleTag.Quickfix],
42
75
  pragma: "##NEEDED",
43
76
  pseudoComment: "EC NEEDED",
@@ -68,67 +101,91 @@ class UnusedVariables {
68
101
  if (syntax.issues.length > 0) {
69
102
  return [];
70
103
  }
71
- const results = this.traverse(syntax.spaghetti.getTop(), obj);
72
- // remove duplicates, quick and dirty
73
- const deduplicated = [];
74
- for (const result of results) {
75
- let cont = false;
76
- for (const d of deduplicated) {
77
- if (result.getStart().equals(d.getStart())) {
78
- cont = true;
79
- break;
80
- }
81
- }
82
- if (cont === true) {
104
+ this.workarea = new WorkArea();
105
+ const top = syntax.spaghetti.getTop();
106
+ this.buildWorkarea(top, obj);
107
+ if (this.workarea.count() === 0) {
108
+ return this.buildIssues(obj); // exit early if all types are used
109
+ }
110
+ this.findUses(top, obj);
111
+ for (const o of this.reg.getObjects()) {
112
+ if (o === obj) {
83
113
  continue;
84
114
  }
85
- deduplicated.push(result);
115
+ else if (o instanceof _abap_object_1.ABAPObject) {
116
+ if (this.reg.isDependency(o)) {
117
+ continue; // do not search in dependencies
118
+ }
119
+ const syntax = new syntax_1.SyntaxLogic(this.reg, o).run();
120
+ this.findUses(syntax.spaghetti.getTop(), o);
121
+ if (this.workarea.count() === 0) {
122
+ return this.buildIssues(obj); // exit early if all types are used
123
+ }
124
+ }
86
125
  }
87
- return deduplicated;
126
+ return this.buildIssues(obj);
88
127
  }
89
- traverse(node, obj) {
90
- const ret = [];
91
- if (node.getIdentifier().stype === _scope_type_1.ScopeType.OpenSQL) {
92
- return [];
93
- }
94
- if (node.getIdentifier().stype !== _scope_type_1.ScopeType.BuiltIn) {
95
- ret.push(...this.checkNode(node, obj));
128
+ findUses(node, obj) {
129
+ for (const r of node.getData().references) {
130
+ if (r.referenceType === _reference_1.ReferenceType.DataReadReference
131
+ || r.referenceType === _reference_1.ReferenceType.DataWriteReference
132
+ || r.referenceType === _reference_1.ReferenceType.TypeReference) {
133
+ this.workarea.removeIfExists(r.resolved);
134
+ }
96
135
  }
97
136
  for (const c of node.getChildren()) {
98
- ret.push(...this.traverse(c, obj));
137
+ this.findUses(c, obj);
99
138
  }
100
- return ret;
101
139
  }
102
- checkNode(node, obj) {
140
+ buildWorkarea(node, obj) {
103
141
  var _a;
142
+ const stype = node.getIdentifier().stype;
143
+ if (stype === _scope_type_1.ScopeType.OpenSQL) {
144
+ return;
145
+ }
146
+ for (const c of node.getChildren()) {
147
+ this.buildWorkarea(c, obj);
148
+ }
149
+ if (stype !== _scope_type_1.ScopeType.BuiltIn) {
150
+ const vars = node.getData().vars;
151
+ for (const name in vars) {
152
+ const meta = vars[name].getMeta();
153
+ if (((_a = this.conf.skipNames) === null || _a === void 0 ? void 0 : _a.length) > 0
154
+ && this.conf.skipNames.some((a) => a.toUpperCase() === name)) {
155
+ continue;
156
+ }
157
+ else if (name === "ME"
158
+ || name === "SUPER"
159
+ || meta.includes("event_parameter" /* EventParameter */)) {
160
+ // todo, workaround for "me" and "super", these should somehow be typed to built-in
161
+ continue;
162
+ }
163
+ const isInline = meta.includes("inline" /* InlineDefinition */);
164
+ this.workarea.push(vars[name], isInline ? 2 : 1);
165
+ }
166
+ }
167
+ }
168
+ buildIssues(obj) {
104
169
  const ret = [];
105
- const vars = node.getData().vars;
106
- for (const name in vars) {
107
- if (((_a = this.conf.skipNames) === null || _a === void 0 ? void 0 : _a.length) > 0
108
- && this.conf.skipNames.some((a) => a.toUpperCase() === name)) {
170
+ for (const w of this.workarea.get()) {
171
+ const filename = w.id.getFilename();
172
+ if (this.reg.isFileDependency(filename) === true) {
109
173
  continue;
110
174
  }
111
- if (name === "ME"
112
- || name === "SUPER"
113
- || vars[name].getMeta().includes("event_parameter" /* EventParameter */)) {
114
- // todo, workaround for "me" and "super", these should somehow be typed to built-in
175
+ else if (obj instanceof objects_1.Program === false && obj.containsFile(filename) === false) {
115
176
  continue;
116
177
  }
117
- else if ((obj.containsFile(vars[name].getFilename())
118
- || node.getIdentifier().stype === _scope_type_1.ScopeType.Program
119
- || node.getIdentifier().stype === _scope_type_1.ScopeType.Form)
120
- && this.isUsed(vars[name], node) === false) {
121
- const message = "Variable \"" + name.toLowerCase() + "\" not used";
122
- const statement = this.findStatement(vars[name]);
123
- if (statement === null || statement === void 0 ? void 0 : statement.getPragmas().map(t => t.getStr()).includes(this.getMetadata().pragma + "")) {
124
- continue;
125
- }
126
- else if (this.suppressedbyPseudo(statement, vars[name], obj)) {
127
- continue;
128
- }
129
- const fix = this.buildFix(vars[name], obj);
130
- ret.push(issue_1.Issue.atIdentifier(vars[name], message, this.getMetadata().key, this.conf.severity, fix));
178
+ const statement = this.findStatement(w.id);
179
+ if (statement === null || statement === void 0 ? void 0 : statement.getPragmas().map(t => t.getStr()).includes(this.getMetadata().pragma + "")) {
180
+ continue;
131
181
  }
182
+ else if (this.suppressedbyPseudo(statement, w.id, obj)) {
183
+ continue;
184
+ }
185
+ const name = w.id.getName();
186
+ const message = "Variable \"" + name.toLowerCase() + "\" not used";
187
+ const fix = this.buildFix(w.id, obj);
188
+ ret.push(issue_1.Issue.atIdentifier(w.id, message, this.getMetadata().key, this.conf.severity, fix));
132
189
  }
133
190
  return ret;
134
191
  }
@@ -151,16 +208,6 @@ class UnusedVariables {
151
208
  }
152
209
  return false;
153
210
  }
154
- isUsed(id, node) {
155
- const isInline = id.getMeta().includes("inline" /* InlineDefinition */);
156
- const found = new references_1.References(this.reg).search(id, node, true, isInline === false);
157
- if (isInline === true) {
158
- return found.length > 2; // inline definitions are always written to
159
- }
160
- else {
161
- return found.length > 1;
162
- }
163
- }
164
211
  findStatement(v) {
165
212
  const file = this.reg.getFileByName(v.getFilename());
166
213
  if (file === undefined) {
package/package.json CHANGED
@@ -1,29 +1,19 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.80.5",
3
+ "version": "2.80.9",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
7
7
  "scripts": {
8
- "madge.orphans": "madge --extensions ts --ts-config tsconfig.json --orphans src/",
9
- "madge.svg": "madge --extensions ts --ts-config tsconfig.json --image graph.svg src/",
10
- "madge.circular": "madge --extensions ts --ts-config tsconfig.json --circular src/",
11
8
  "lint": "eslint src/**/*.ts test/**/*.ts --format unix",
12
9
  "lint:fix": "eslint src/**/*.ts test/**/*.ts --format unix --fix",
13
- "compile": "tsc",
14
- "postcompile": "sh scripts/version.sh",
15
- "pretest": "npm run compile",
16
- "test": "mocha --timeout 1000",
10
+ "compile": "tsc && sh scripts/version.sh",
11
+ "test": "npm run compile && mocha --timeout 1000 && npm run lint && npm run schema && api-extractor run",
17
12
  "test:only": "npm run compile && mocha",
18
13
  "test:parallel": "npm run compile && mocha --timeout 1000 --parallel --reporter dot",
19
- "posttest": "npm run lint && npm run schema && api-extractor run",
20
- "prepublishOnly": "rm -rf build && npm run test",
21
- "precoverage": "npm run compile",
22
- "coverage": "c8 mocha",
23
- "postcoverage": "c8 report --reporter=html",
24
- "preschema": "node scripts/schema.js > scripts/schema.ts",
25
- "schema": "ts-json-schema-generator --tsconfig tsconfig_schema.json --jsDoc extended --path scripts/schema.ts > scripts/schema.json",
26
- "postschema": "node scripts/schema_post.js"
14
+ "coverage": "npm run compile && c8 mocha && c8 report --reporter=html",
15
+ "schema": "node scripts/schema.js > scripts/schema.ts && ts-json-schema-generator --tsconfig tsconfig_schema.json --jsDoc extended --path scripts/schema.ts > scripts/schema.json && node scripts/schema_post.js",
16
+ "publish:patch": "npm --no-git-tag-version version patch && rm -rf build && npm install && npm run test && npm publish --access public"
27
17
  },
28
18
  "mocha": {
29
19
  "recursive": true,
@@ -54,13 +44,12 @@
54
44
  },
55
45
  "homepage": "https://abaplint.org",
56
46
  "devDependencies": {
57
- "@microsoft/api-extractor": "^7.18.17",
47
+ "@microsoft/api-extractor": "^7.18.19",
58
48
  "@types/chai": "^4.2.22",
59
49
  "@types/mocha": "^9.0.0",
60
- "@types/node": "^16.11.6",
50
+ "@types/node": "^16.11.7",
61
51
  "chai": "^4.3.4",
62
- "eslint": "^8.1.0",
63
- "madge": "^5.0.1",
52
+ "eslint": "^8.2.0",
64
53
  "mocha": "^9.1.3",
65
54
  "c8": "^7.10.0",
66
55
  "source-map-support": "^0.5.20",