@abaplint/core 2.120.4 → 2.120.6
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.
- package/build/abaplint.d.ts +3 -2
- package/build/src/abap/5_syntax/expressions/cond_body.js +1 -1
- package/build/src/abap/5_syntax/expressions/inline_data.js +4 -0
- package/build/src/abap/5_syntax/expressions/inline_fs.js +6 -0
- package/build/src/abap/5_syntax/expressions/source.js +1 -1
- package/build/src/abap/5_syntax/expressions/switch_body.js +3 -3
- package/build/src/abap/5_syntax/statements/at_selection_screen.js +59 -0
- package/build/src/abap/5_syntax/statements/constant.js +11 -0
- package/build/src/abap/5_syntax/statements/data.js +11 -0
- package/build/src/abap/5_syntax/statements/fieldsymbol.js +8 -3
- package/build/src/abap/5_syntax/syntax.js +8 -5
- package/build/src/abap/types/class_definition.js +12 -0
- package/build/src/registry.js +1 -1
- package/build/src/rules/unused_variables.js +60 -53
- package/package.json +1 -1
package/build/abaplint.d.ts
CHANGED
|
@@ -1259,6 +1259,7 @@ declare class ClassDefinition_3 extends Identifier implements IClassDefinition {
|
|
|
1259
1259
|
private findSuper;
|
|
1260
1260
|
private checkMethodNameLength;
|
|
1261
1261
|
private checkClassConstructorStatic;
|
|
1262
|
+
private checkInterfaceVisibility;
|
|
1262
1263
|
private checkMethodsFromSuperClasses;
|
|
1263
1264
|
private findFriends;
|
|
1264
1265
|
private addReference;
|
|
@@ -7850,8 +7851,8 @@ export declare class SyntaxLogic {
|
|
|
7850
7851
|
private issues;
|
|
7851
7852
|
private readonly object;
|
|
7852
7853
|
private readonly reg;
|
|
7853
|
-
private
|
|
7854
|
-
private
|
|
7854
|
+
private scope;
|
|
7855
|
+
private helpers;
|
|
7855
7856
|
constructor(reg: IRegistry, object: ABAPObject);
|
|
7856
7857
|
run(): ISyntaxResult;
|
|
7857
7858
|
private traverseObject;
|
|
@@ -57,7 +57,7 @@ class CondBody {
|
|
|
57
57
|
type = source_1.Source.runSyntax(s, input, targetType);
|
|
58
58
|
}
|
|
59
59
|
else {
|
|
60
|
-
source_1.Source.runSyntax(s, input, targetType);
|
|
60
|
+
source_1.Source.runSyntax(s, input, targetType !== null && targetType !== void 0 ? targetType : type);
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
if (scoped === true) {
|
|
@@ -43,6 +43,10 @@ class InlineData {
|
|
|
43
43
|
static runSyntax(node, input, type) {
|
|
44
44
|
var _a;
|
|
45
45
|
const token = (_a = node.findFirstExpression(Expressions.TargetField)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
46
|
+
if (token && token.getStr().length > 30) {
|
|
47
|
+
const message = "DATA name too long, " + token.getStr();
|
|
48
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, token, message));
|
|
49
|
+
}
|
|
46
50
|
if (token && type) {
|
|
47
51
|
if (type instanceof basic_1.CSequenceType || type instanceof basic_1.CLikeType) {
|
|
48
52
|
type = basic_1.StringType.get();
|
|
@@ -38,10 +38,16 @@ const Expressions = __importStar(require("../../2_statements/expressions"));
|
|
|
38
38
|
const _typed_identifier_1 = require("../../types/_typed_identifier");
|
|
39
39
|
const basic_1 = require("../../types/basic");
|
|
40
40
|
const _reference_1 = require("../_reference");
|
|
41
|
+
const _syntax_input_1 = require("../_syntax_input");
|
|
41
42
|
class InlineFS {
|
|
42
43
|
static runSyntax(node, input, type) {
|
|
43
44
|
var _a;
|
|
44
45
|
const token = (_a = node.findFirstExpression(Expressions.TargetFieldSymbol)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
46
|
+
const fs = node.findFirstExpression(Expressions.FieldSymbol);
|
|
47
|
+
if (fs && fs.concatTokens().length > 30) {
|
|
48
|
+
const message = "FIELD-SYMBOLS name too long, " + fs.concatTokens();
|
|
49
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, fs.getFirstToken(), message));
|
|
50
|
+
}
|
|
45
51
|
if (token && type) {
|
|
46
52
|
const identifier = new _typed_identifier_1.TypedIdentifier(token, input.filename, type, ["inline" /* IdentifierMeta.InlineDefinition */]);
|
|
47
53
|
input.scope.addIdentifier(identifier);
|
|
@@ -117,7 +117,7 @@ class Source {
|
|
|
117
117
|
case "SWITCH":
|
|
118
118
|
{
|
|
119
119
|
const foundType = this.determineType(node, input, targetType);
|
|
120
|
-
const bodyType = switch_body_1.SwitchBody.runSyntax(node.findDirectExpression(Expressions.SwitchBody), input);
|
|
120
|
+
const bodyType = switch_body_1.SwitchBody.runSyntax(node.findDirectExpression(Expressions.SwitchBody), input, foundType);
|
|
121
121
|
if (foundType === undefined || foundType.isGeneric()) {
|
|
122
122
|
this.addIfInferred(node, input, bodyType);
|
|
123
123
|
}
|
|
@@ -39,7 +39,7 @@ const source_1 = require("./source");
|
|
|
39
39
|
const _syntax_input_1 = require("../_syntax_input");
|
|
40
40
|
const basic_1 = require("../../types/basic");
|
|
41
41
|
class SwitchBody {
|
|
42
|
-
static runSyntax(node, input) {
|
|
42
|
+
static runSyntax(node, input, targetType) {
|
|
43
43
|
if (node === undefined) {
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
@@ -49,12 +49,12 @@ class SwitchBody {
|
|
|
49
49
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
50
50
|
return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
|
|
51
51
|
}
|
|
52
|
-
const type = source_1.Source.runSyntax(thenSource, input);
|
|
52
|
+
const type = source_1.Source.runSyntax(thenSource, input, targetType);
|
|
53
53
|
for (const s of node.findDirectExpressions(Expressions.Source)) {
|
|
54
54
|
if (s === thenSource) {
|
|
55
55
|
continue;
|
|
56
56
|
}
|
|
57
|
-
source_1.Source.runSyntax(s, input);
|
|
57
|
+
source_1.Source.runSyntax(s, input, targetType !== null && targetType !== void 0 ? targetType : type);
|
|
58
58
|
}
|
|
59
59
|
return type;
|
|
60
60
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
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.AtSelectionScreen = void 0;
|
|
37
|
+
const Expressions = __importStar(require("../../2_statements/expressions"));
|
|
38
|
+
const _reference_1 = require("../_reference");
|
|
39
|
+
const source_field_1 = require("../expressions/source_field");
|
|
40
|
+
class AtSelectionScreen {
|
|
41
|
+
runSyntax(node, input) {
|
|
42
|
+
// "AT SELECTION-SCREEN ON <field>", "ON VALUE-REQUEST FOR <field>",
|
|
43
|
+
// "ON HELP-REQUEST FOR <field>" and "ON END OF <field>" all reference
|
|
44
|
+
// a parameter or select-option, register these as read references so
|
|
45
|
+
// they are not reported as unused.
|
|
46
|
+
const fields = [
|
|
47
|
+
...node.findDirectExpressions(Expressions.FieldSub),
|
|
48
|
+
...node.findDirectExpressions(Expressions.Field),
|
|
49
|
+
];
|
|
50
|
+
for (const field of fields) {
|
|
51
|
+
const token = field.getFirstToken();
|
|
52
|
+
if (input.scope.findVariable(token.getStr()) !== undefined) {
|
|
53
|
+
source_field_1.SourceField.runSyntax(field, input, _reference_1.ReferenceType.DataReadReference, false);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.AtSelectionScreen = AtSelectionScreen;
|
|
59
|
+
//# sourceMappingURL=at_selection_screen.js.map
|
|
@@ -53,6 +53,10 @@ class Constant {
|
|
|
53
53
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, found.getToken(), message));
|
|
54
54
|
return new _typed_identifier_1.TypedIdentifier(found.getToken(), input.filename, basic_2.VoidType.get(_syntax_input_1.CheckSyntaxKey), meta, val);
|
|
55
55
|
}
|
|
56
|
+
if (this.isNameTooLong(found.getName())) {
|
|
57
|
+
const message = "CONSTANTS name too long, " + found.getName();
|
|
58
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, found.getToken(), message));
|
|
59
|
+
}
|
|
56
60
|
return new _typed_identifier_1.TypedIdentifier(found.getToken(), input.filename, found.getType(), meta, val);
|
|
57
61
|
}
|
|
58
62
|
const fallback = node.findFirstExpression(Expressions.DefinitionName);
|
|
@@ -61,10 +65,17 @@ class Constant {
|
|
|
61
65
|
const message = "not possible to have a name with only digits";
|
|
62
66
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, fallback.getFirstToken(), message));
|
|
63
67
|
}
|
|
68
|
+
if (this.isNameTooLong(fallback.concatTokens())) {
|
|
69
|
+
const message = "CONSTANTS name too long, " + fallback.concatTokens();
|
|
70
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, fallback.getFirstToken(), message));
|
|
71
|
+
}
|
|
64
72
|
return new _typed_identifier_1.TypedIdentifier(fallback.getFirstToken(), input.filename, new basic_1.UnknownType("constant, fallback"));
|
|
65
73
|
}
|
|
66
74
|
throw new assert_error_1.AssertError("Statement Constant: unexpected structure");
|
|
67
75
|
}
|
|
76
|
+
isNameTooLong(name) {
|
|
77
|
+
return name.length > 30;
|
|
78
|
+
}
|
|
68
79
|
isOnlyDigits(name) {
|
|
69
80
|
return /^[0-9]+$/.test(name);
|
|
70
81
|
}
|
|
@@ -51,6 +51,10 @@ class Data {
|
|
|
51
51
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, id.getToken(), message));
|
|
52
52
|
return new _typed_identifier_1.TypedIdentifier(id.getToken(), input.filename, basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey));
|
|
53
53
|
}
|
|
54
|
+
if (id && this.isNameTooLong(id.getName())) {
|
|
55
|
+
const message = "DATA name too long, " + id.getName();
|
|
56
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, id.getToken(), message));
|
|
57
|
+
}
|
|
54
58
|
if ((id === null || id === void 0 ? void 0 : id.getType().isGeneric()) === true
|
|
55
59
|
&& (id === null || id === void 0 ? void 0 : id.getType().containsVoid()) === false) {
|
|
56
60
|
const message = "DATA definition cannot be generic, " + (name === null || name === void 0 ? void 0 : name.concatTokens());
|
|
@@ -64,10 +68,17 @@ class Data {
|
|
|
64
68
|
const message = "not possible to have a name with only digits";
|
|
65
69
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, name.getFirstToken(), message));
|
|
66
70
|
}
|
|
71
|
+
if (this.isNameTooLong(name.concatTokens())) {
|
|
72
|
+
const message = "DATA name too long, " + name.concatTokens();
|
|
73
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, name.getFirstToken(), message));
|
|
74
|
+
}
|
|
67
75
|
return new _typed_identifier_1.TypedIdentifier(name.getFirstToken(), input.filename, new unknown_type_1.UnknownType("data, fallback"));
|
|
68
76
|
}
|
|
69
77
|
return undefined;
|
|
70
78
|
}
|
|
79
|
+
isNameTooLong(name) {
|
|
80
|
+
return name.length > 30;
|
|
81
|
+
}
|
|
71
82
|
isOnlyDigits(name) {
|
|
72
83
|
return /^[0-9]+$/.test(name);
|
|
73
84
|
}
|
|
@@ -38,14 +38,19 @@ const Expressions = __importStar(require("../../2_statements/expressions"));
|
|
|
38
38
|
const _typed_identifier_1 = require("../../types/_typed_identifier");
|
|
39
39
|
const basic_types_1 = require("../basic_types");
|
|
40
40
|
const unknown_type_1 = require("../../types/basic/unknown_type");
|
|
41
|
+
const _syntax_input_1 = require("../_syntax_input");
|
|
41
42
|
const basic_1 = require("../../types/basic");
|
|
42
43
|
class FieldSymbol {
|
|
43
44
|
runSyntax(node, input) {
|
|
44
|
-
|
|
45
|
-
const fsname =
|
|
46
|
-
if (fsname === undefined) {
|
|
45
|
+
const fs = node.findFirstExpression(Expressions.FieldSymbol);
|
|
46
|
+
const fsname = fs === null || fs === void 0 ? void 0 : fs.getFirstToken();
|
|
47
|
+
if (fs === undefined || fsname === undefined) {
|
|
47
48
|
return;
|
|
48
49
|
}
|
|
50
|
+
if (fs.concatTokens().length > 30) {
|
|
51
|
+
const message = "FIELD-SYMBOLS name too long, " + fs.concatTokens();
|
|
52
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, fsname, message));
|
|
53
|
+
}
|
|
49
54
|
if (node.getChildren().length === 5) {
|
|
50
55
|
// no type specified
|
|
51
56
|
input.scope.addIdentifier(new _typed_identifier_1.TypedIdentifier(fsname, input.filename, basic_1.VoidType.get("FS-SIMPLE")));
|
|
@@ -90,6 +90,7 @@ const if_1 = require("./statements/if");
|
|
|
90
90
|
const else_if_1 = require("./statements/else_if");
|
|
91
91
|
const append_1 = require("./statements/append");
|
|
92
92
|
const selection_screen_1 = require("./statements/selection_screen");
|
|
93
|
+
const at_selection_screen_1 = require("./statements/at_selection_screen");
|
|
93
94
|
const ranges_1 = require("./statements/ranges");
|
|
94
95
|
const write_1 = require("./statements/write");
|
|
95
96
|
const case_1 = require("./statements/case");
|
|
@@ -297,6 +298,7 @@ if (Object.keys(map).length === 0) {
|
|
|
297
298
|
addToMap(new authority_check_1.AuthorityCheck());
|
|
298
299
|
addToMap(new insert_report_1.InsertReport());
|
|
299
300
|
addToMap(new selection_screen_1.SelectionScreen());
|
|
301
|
+
addToMap(new at_selection_screen_1.AtSelectionScreen());
|
|
300
302
|
addToMap(new ranges_1.Ranges());
|
|
301
303
|
addToMap(new add_1.Add());
|
|
302
304
|
addToMap(new raise_event_1.RaiseEvent());
|
|
@@ -335,16 +337,17 @@ class SyntaxLogic {
|
|
|
335
337
|
this.reg = reg;
|
|
336
338
|
this.issues = [];
|
|
337
339
|
this.object = object;
|
|
338
|
-
this.scope = _current_scope_1.CurrentScope.buildDefault(this.reg, object);
|
|
339
|
-
this.helpers = {
|
|
340
|
-
oooc: new _object_oriented_1.ObjectOriented(this.scope),
|
|
341
|
-
proc: new _procedural_1.Procedural(this.reg, this.scope),
|
|
342
|
-
};
|
|
343
340
|
}
|
|
344
341
|
run() {
|
|
345
342
|
if (this.object.syntaxResult !== undefined) {
|
|
346
343
|
return this.object.syntaxResult;
|
|
347
344
|
}
|
|
345
|
+
// the scope is built here instead of in the constructor, cached results must stay cheap
|
|
346
|
+
this.scope = _current_scope_1.CurrentScope.buildDefault(this.reg, this.object);
|
|
347
|
+
this.helpers = {
|
|
348
|
+
oooc: new _object_oriented_1.ObjectOriented(this.scope),
|
|
349
|
+
proc: new _procedural_1.Procedural(this.reg, this.scope),
|
|
350
|
+
};
|
|
348
351
|
this.issues = [];
|
|
349
352
|
this.reg.getDDICReferences().clear(this.object);
|
|
350
353
|
this.reg.getMSAGReferences().clear(this.object);
|
|
@@ -95,6 +95,7 @@ class ClassDefinition extends _identifier_1.Identifier {
|
|
|
95
95
|
this.createVisibilityValue = visibility_1.Visibility.Public;
|
|
96
96
|
}
|
|
97
97
|
// perform checks after everything has been initialized
|
|
98
|
+
this.checkInterfaceVisibility(input, node);
|
|
98
99
|
this.checkMethodsFromSuperClasses(input);
|
|
99
100
|
this.checkMethodNameLength(input);
|
|
100
101
|
this.checkClassConstructorStatic(input);
|
|
@@ -168,6 +169,17 @@ class ClassDefinition extends _identifier_1.Identifier {
|
|
|
168
169
|
}
|
|
169
170
|
}
|
|
170
171
|
}
|
|
172
|
+
checkInterfaceVisibility(input, node) {
|
|
173
|
+
const sections = [
|
|
174
|
+
node.findDirectStructure(Structures.ProtectedSection),
|
|
175
|
+
node.findDirectStructure(Structures.PrivateSection),
|
|
176
|
+
];
|
|
177
|
+
for (const section of sections) {
|
|
178
|
+
for (const statement of (section === null || section === void 0 ? void 0 : section.findAllStatements(Statements.InterfaceDef)) || []) {
|
|
179
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, statement.getFirstToken(), "INTERFACES can only be declared in public sections"));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
171
183
|
checkMethodsFromSuperClasses(input) {
|
|
172
184
|
var _a;
|
|
173
185
|
const scope = input.scope;
|
package/build/src/registry.js
CHANGED
|
@@ -59,35 +59,38 @@ class UnusedVariablesConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
|
59
59
|
exports.UnusedVariablesConf = UnusedVariablesConf;
|
|
60
60
|
class WorkArea {
|
|
61
61
|
constructor() {
|
|
62
|
-
this
|
|
62
|
+
// keyed by filename + start position, this equals Identifier.equals()
|
|
63
|
+
this.workarea = new Map();
|
|
63
64
|
}
|
|
64
65
|
push(id, count = 1) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
66
|
+
const key = this.buildKey(id);
|
|
67
|
+
if (this.workarea.has(key)) {
|
|
68
|
+
return;
|
|
69
69
|
}
|
|
70
|
-
this.workarea.
|
|
70
|
+
this.workarea.set(key, { id, count });
|
|
71
71
|
}
|
|
72
72
|
removeIfExists(id) {
|
|
73
73
|
if (id === undefined) {
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return;
|
|
76
|
+
const key = this.buildKey(id);
|
|
77
|
+
const found = this.workarea.get(key);
|
|
78
|
+
if (found !== undefined) {
|
|
79
|
+
found.count--;
|
|
80
|
+
if (found.count === 0) {
|
|
81
|
+
this.workarea.delete(key);
|
|
83
82
|
}
|
|
84
83
|
}
|
|
85
84
|
}
|
|
86
85
|
get() {
|
|
87
|
-
return this.workarea;
|
|
86
|
+
return [...this.workarea.values()];
|
|
88
87
|
}
|
|
89
88
|
count() {
|
|
90
|
-
return this.workarea.
|
|
89
|
+
return this.workarea.size;
|
|
90
|
+
}
|
|
91
|
+
buildKey(id) {
|
|
92
|
+
const start = id.getStart();
|
|
93
|
+
return id.getFilename() + "," + start.getRow() + "," + start.getCol();
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
96
|
class UnusedVariables {
|
|
@@ -221,6 +224,9 @@ Errors found in INCLUDES are reported for the main program.`,
|
|
|
221
224
|
}
|
|
222
225
|
buildIssues(obj) {
|
|
223
226
|
const ret = [];
|
|
227
|
+
const metadata = this.getMetadata();
|
|
228
|
+
const pragma = metadata.pragma + "";
|
|
229
|
+
const files = new Map();
|
|
224
230
|
for (const w of this.workarea.get()) {
|
|
225
231
|
const filename = w.id.getFilename();
|
|
226
232
|
if (this.reg.isFileDependency(filename) === true) {
|
|
@@ -229,41 +235,51 @@ Errors found in INCLUDES are reported for the main program.`,
|
|
|
229
235
|
else if (obj instanceof objects_1.Program === false && obj.containsFile(filename) === false) {
|
|
230
236
|
continue;
|
|
231
237
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
continue;
|
|
238
|
+
if (files.has(filename) === false) {
|
|
239
|
+
files.set(filename, this.findFile(filename));
|
|
235
240
|
}
|
|
236
|
-
|
|
237
|
-
|
|
241
|
+
const file = files.get(filename);
|
|
242
|
+
let statement = undefined;
|
|
243
|
+
let statementIndex = -1;
|
|
244
|
+
if (file !== undefined) {
|
|
245
|
+
const statements = file.getStatements();
|
|
246
|
+
const token = w.id.getToken();
|
|
247
|
+
for (let i = 0; i < statements.length; i++) {
|
|
248
|
+
if (statements[i].includesToken(token)) {
|
|
249
|
+
statement = statements[i];
|
|
250
|
+
statementIndex = i;
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (statement !== undefined && file !== undefined) {
|
|
256
|
+
if (statement.getPragmas().some(t => t.getStr() === pragma)) {
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
else if (this.suppressedbyPseudo(file, statementIndex, w.id, obj)) {
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
238
262
|
}
|
|
239
263
|
const name = w.id.getName();
|
|
240
264
|
const message = "Variable \"" + name.toLowerCase() + "\" not used";
|
|
241
|
-
const fix = this.buildFix(w.id, obj);
|
|
242
|
-
ret.push(issue_1.Issue.atIdentifier(w.id, message,
|
|
265
|
+
const fix = this.buildFix(w.id, obj, statement);
|
|
266
|
+
ret.push(issue_1.Issue.atIdentifier(w.id, message, metadata.key, this.conf.severity, fix));
|
|
243
267
|
}
|
|
244
268
|
return ret;
|
|
245
269
|
}
|
|
246
|
-
suppressedbyPseudo(
|
|
247
|
-
|
|
270
|
+
suppressedbyPseudo(file, statementIndex, v, obj) {
|
|
271
|
+
// pseudo comments are only found in files belonging to the object itself, not in eg. includes
|
|
272
|
+
if (obj.getABAPFileByName(v.getFilename()) === undefined) {
|
|
248
273
|
return false;
|
|
249
274
|
}
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
let next = false;
|
|
255
|
-
for (const s of file.getStatements()) {
|
|
256
|
-
if (next === true && s.get() instanceof _statement_1.Comment) {
|
|
257
|
-
return s.concatTokens().includes(this.getMetadata().pseudoComment + "");
|
|
258
|
-
}
|
|
259
|
-
if (s === statement) {
|
|
260
|
-
next = true;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
275
|
+
const statements = file.getStatements();
|
|
276
|
+
const next = statements[statementIndex + 1];
|
|
277
|
+
return (next === null || next === void 0 ? void 0 : next.get()) instanceof _statement_1.Comment
|
|
278
|
+
&& next.concatTokens().includes(this.getMetadata().pseudoComment + "");
|
|
263
279
|
return false;
|
|
264
280
|
}
|
|
265
|
-
|
|
266
|
-
const file = this.reg.getFileByName(
|
|
281
|
+
findFile(filename) {
|
|
282
|
+
const file = this.reg.getFileByName(filename);
|
|
267
283
|
if (file === undefined) {
|
|
268
284
|
return undefined;
|
|
269
285
|
}
|
|
@@ -271,26 +287,17 @@ Errors found in INCLUDES are reported for the main program.`,
|
|
|
271
287
|
if (!(object instanceof _abap_object_1.ABAPObject)) {
|
|
272
288
|
return undefined;
|
|
273
289
|
}
|
|
274
|
-
|
|
275
|
-
|
|
290
|
+
return object.getABAPFileByName(filename);
|
|
291
|
+
}
|
|
292
|
+
buildFix(v, obj, statement) {
|
|
293
|
+
if (statement === undefined || !(statement.get() instanceof Statements.Data)) {
|
|
276
294
|
return undefined;
|
|
277
295
|
}
|
|
278
|
-
const statement = edit_helper_1.EditHelper.findStatement(v.getToken(), abapfile);
|
|
279
|
-
return statement;
|
|
280
|
-
}
|
|
281
|
-
buildFix(v, obj) {
|
|
282
296
|
const file = obj.getABAPFileByName(v.getFilename());
|
|
283
297
|
if (file === undefined) {
|
|
284
298
|
return undefined;
|
|
285
299
|
}
|
|
286
|
-
|
|
287
|
-
if (statement === undefined) {
|
|
288
|
-
return undefined;
|
|
289
|
-
}
|
|
290
|
-
else if (statement.get() instanceof Statements.Data) {
|
|
291
|
-
return edit_helper_1.EditHelper.deleteStatement(file, statement);
|
|
292
|
-
}
|
|
293
|
-
return undefined;
|
|
300
|
+
return edit_helper_1.EditHelper.deleteStatement(file, statement);
|
|
294
301
|
}
|
|
295
302
|
}
|
|
296
303
|
exports.UnusedVariables = UnusedVariables;
|