@abaplint/core 2.113.136 → 2.113.138
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 +2 -0
- package/build/src/abap/2_statements/expressions/message_class.js +1 -1
- package/build/src/abap/2_statements/statements/read_table.js +1 -1
- package/build/src/registry.js +4 -5
- package/build/src/rules_runner.js +40 -1
- package/build/src/utils/include_graph.js +25 -27
- package/package.json +1 -1
package/build/abaplint.d.ts
CHANGED
|
@@ -5570,6 +5570,7 @@ export declare class Registry implements IRegistry {
|
|
|
5570
5570
|
private readonly ddicReferences;
|
|
5571
5571
|
private readonly msagReferences;
|
|
5572
5572
|
private readonly macroReferences;
|
|
5573
|
+
private errorNamespace;
|
|
5573
5574
|
private conf;
|
|
5574
5575
|
constructor(conf?: IConfiguration);
|
|
5575
5576
|
static abaplintVersion(): string;
|
|
@@ -5710,6 +5711,7 @@ declare class RollbackEntities implements IStatement {
|
|
|
5710
5711
|
|
|
5711
5712
|
export declare class RulesRunner {
|
|
5712
5713
|
private readonly reg;
|
|
5714
|
+
private readonly syntaxPerformance;
|
|
5713
5715
|
constructor(reg: IRegistry);
|
|
5714
5716
|
objectsToCheck(objects: Iterable<IObject>): readonly IObject[];
|
|
5715
5717
|
runRules(objects: Iterable<IObject>, input?: IRunInput): readonly Issue[];
|
|
@@ -6,7 +6,7 @@ const combi_1 = require("../combi");
|
|
|
6
6
|
class MessageClass extends combi_1.Expression {
|
|
7
7
|
getRunnable() {
|
|
8
8
|
// "&1" can be used for almost anything(field names, method names etc.) in macros
|
|
9
|
-
return (0, combi_1.seq)((0, combi_1.regex)(/^>?[\w\/]
|
|
9
|
+
return (0, combi_1.seq)((0, combi_1.regex)(/^>?[\w\/]+#?@?\/?!?&?>?\$?\??<?§?~?$/), (0, combi_1.starPrio)((0, combi_1.tok)(tokens_1.Plus)), (0, combi_1.starPrio)((0, combi_1.tok)(tokens_1.PlusW)), (0, combi_1.starPrio)((0, combi_1.seq)((0, combi_1.tok)(tokens_1.Dash), (0, combi_1.optPrio)((0, combi_1.regex)(/^\w+$/)))), (0, combi_1.optPrio)((0, combi_1.tok)(tokens_1.DashW)));
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
exports.MessageClass = MessageClass;
|
|
@@ -7,7 +7,7 @@ const version_1 = require("../../../version");
|
|
|
7
7
|
const transporting_fields_1 = require("../expressions/transporting_fields");
|
|
8
8
|
class ReadTable {
|
|
9
9
|
getMatcher() {
|
|
10
|
-
const comparing = (0, combi_1.seq)("COMPARING", (0, combi_1.alt)((0, combi_1.plus)(expressions_1.FieldSub), expressions_1.Dynamic));
|
|
10
|
+
const comparing = (0, combi_1.seq)("COMPARING", (0, combi_1.alt)((0, combi_1.plus)(expressions_1.FieldSub), (0, combi_1.plus)(expressions_1.Dynamic)));
|
|
11
11
|
const index = (0, combi_1.seq)("INDEX", expressions_1.Source);
|
|
12
12
|
const components = (0, combi_1.seq)((0, combi_1.alt)(expressions_1.Field, expressions_1.Dynamic), "COMPONENTS", expressions_1.ComponentCompareSimple);
|
|
13
13
|
const key = (0, combi_1.seq)((0, combi_1.altPrio)("WITH KEY", "WITH TABLE KEY"), (0, combi_1.alt)(expressions_1.ComponentCompareSimple, components, (0, combi_1.seq)((0, combi_1.optPrio)("="), expressions_1.Source)));
|
package/build/src/registry.js
CHANGED
|
@@ -60,14 +60,14 @@ class Registry {
|
|
|
60
60
|
this.objects = {};
|
|
61
61
|
this.objectsByType = {};
|
|
62
62
|
this.dependencies = {};
|
|
63
|
-
this.conf
|
|
63
|
+
this.setConfig(conf ? conf : config_1.Config.getDefault());
|
|
64
64
|
this.ddicReferences = new ddic_references_1.DDICReferences();
|
|
65
65
|
this.msagReferences = new msag_references_1.MSAGReferences();
|
|
66
66
|
this.macroReferences = new macro_references_1.MacroReferences();
|
|
67
67
|
}
|
|
68
68
|
static abaplintVersion() {
|
|
69
69
|
// magic, see build script "version.sh"
|
|
70
|
-
return "2.113.
|
|
70
|
+
return "2.113.138";
|
|
71
71
|
}
|
|
72
72
|
getDDICReferences() {
|
|
73
73
|
return this.ddicReferences;
|
|
@@ -145,12 +145,11 @@ class Registry {
|
|
|
145
145
|
obj.setDirty();
|
|
146
146
|
}
|
|
147
147
|
this.conf = conf;
|
|
148
|
+
this.errorNamespace = new RegExp(this.getConfig().getSyntaxSetttings().errorNamespace, "i");
|
|
148
149
|
return this;
|
|
149
150
|
}
|
|
150
151
|
inErrorNamespace(name) {
|
|
151
|
-
|
|
152
|
-
const reg = new RegExp(this.getConfig().getSyntaxSetttings().errorNamespace, "i");
|
|
153
|
-
return reg.test(name);
|
|
152
|
+
return this.errorNamespace.test(name);
|
|
154
153
|
}
|
|
155
154
|
addFile(file) {
|
|
156
155
|
return this.addFiles([file]);
|
|
@@ -6,9 +6,35 @@ const artifacts_rules_1 = require("./artifacts_rules");
|
|
|
6
6
|
const _abap_object_1 = require("./objects/_abap_object");
|
|
7
7
|
const skip_logic_1 = require("./skip_logic");
|
|
8
8
|
const excludeHelper_1 = require("./utils/excludeHelper");
|
|
9
|
+
class SyntaxPerformance {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.results = [];
|
|
12
|
+
}
|
|
13
|
+
push(obj, runtime) {
|
|
14
|
+
if (runtime < 100) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
this.results.push({
|
|
18
|
+
runtime: runtime,
|
|
19
|
+
name: obj.getType() + " " + obj.getName(),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
output() {
|
|
23
|
+
const MAX = 10;
|
|
24
|
+
this.results.sort((a, b) => { return b.runtime - a.runtime; });
|
|
25
|
+
for (let i = 0; i < MAX; i++) {
|
|
26
|
+
const row = this.results[i];
|
|
27
|
+
if (row === undefined) {
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
process.stderr.write(`\t${row.runtime}ms\t${row.name}\n`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
9
34
|
class RulesRunner {
|
|
10
35
|
constructor(reg) {
|
|
11
36
|
this.reg = reg;
|
|
37
|
+
this.syntaxPerformance = new SyntaxPerformance();
|
|
12
38
|
}
|
|
13
39
|
objectsToCheck(objects) {
|
|
14
40
|
const check = [];
|
|
@@ -33,12 +59,25 @@ class RulesRunner {
|
|
|
33
59
|
for (const obj of check) {
|
|
34
60
|
(_b = input === null || input === void 0 ? void 0 : input.progress) === null || _b === void 0 ? void 0 : _b.tick("Run Syntax - " + obj.getName());
|
|
35
61
|
if (obj instanceof _abap_object_1.ABAPObject) {
|
|
62
|
+
const start = Date.now();
|
|
36
63
|
new syntax_1.SyntaxLogic(this.reg, obj).run();
|
|
64
|
+
if ((input === null || input === void 0 ? void 0 : input.outputPerformance) === true) {
|
|
65
|
+
this.syntaxPerformance.push(obj, Date.now() - start);
|
|
66
|
+
}
|
|
37
67
|
}
|
|
38
68
|
}
|
|
69
|
+
if ((input === null || input === void 0 ? void 0 : input.outputPerformance) === true) {
|
|
70
|
+
process.stderr.write("Syntax Performance:\n");
|
|
71
|
+
this.syntaxPerformance.output();
|
|
72
|
+
}
|
|
39
73
|
(_c = input === null || input === void 0 ? void 0 : input.progress) === null || _c === void 0 ? void 0 : _c.set(rules.length, "Initialize Rules");
|
|
40
74
|
for (const rule of rules) {
|
|
41
|
-
(
|
|
75
|
+
if ((input === null || input === void 0 ? void 0 : input.outputPerformance) === true) {
|
|
76
|
+
process.stderr.write("Initializing rule " + rule.getMetadata().key + "\n");
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
(_d = input === null || input === void 0 ? void 0 : input.progress) === null || _d === void 0 ? void 0 : _d.tick("Initialize Rules - " + rule.getMetadata().key);
|
|
80
|
+
}
|
|
42
81
|
if (rule.initialize === undefined) {
|
|
43
82
|
throw new Error(rule.getMetadata().key + " missing initialize method");
|
|
44
83
|
}
|
|
@@ -11,6 +11,7 @@ const _abap_object_1 = require("../objects/_abap_object");
|
|
|
11
11
|
const severity_1 = require("../severity");
|
|
12
12
|
// todo, check for cycles/circular dependencies, method findTop
|
|
13
13
|
// todo, add configurable error for multiple use includes
|
|
14
|
+
const FMXXINCLUDE = /^(\/\w+\/)?L.+XX$/;
|
|
14
15
|
function getABAPObjects(reg) {
|
|
15
16
|
const ret = [];
|
|
16
17
|
for (const o of reg.getObjects()) {
|
|
@@ -22,40 +23,33 @@ function getABAPObjects(reg) {
|
|
|
22
23
|
}
|
|
23
24
|
class Graph {
|
|
24
25
|
constructor() {
|
|
25
|
-
this.
|
|
26
|
-
this.
|
|
26
|
+
this.verticesIncludenameIndex = {};
|
|
27
|
+
this.verticesFilenameIndex = {};
|
|
28
|
+
this.edges = {};
|
|
27
29
|
}
|
|
28
30
|
addVertex(vertex) {
|
|
29
|
-
this.
|
|
31
|
+
this.verticesIncludenameIndex[vertex.includeName.toUpperCase()] = vertex;
|
|
32
|
+
this.verticesFilenameIndex[vertex.filename.toUpperCase()] = vertex;
|
|
30
33
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (v.includeName.toUpperCase() === includeName.toUpperCase()) {
|
|
34
|
-
return v;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return undefined;
|
|
34
|
+
findVertexViaIncludename(includeName) {
|
|
35
|
+
return this.verticesIncludenameIndex[includeName.toUpperCase()];
|
|
38
36
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (v.filename.toUpperCase() === filename.toUpperCase()) {
|
|
42
|
-
return v;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return undefined;
|
|
37
|
+
findVertexByFilename(filename) {
|
|
38
|
+
return this.verticesFilenameIndex[filename.toUpperCase()];
|
|
46
39
|
}
|
|
47
40
|
addEdge(from, toFilename) {
|
|
48
|
-
this.edges
|
|
41
|
+
if (this.edges[from.filename] === undefined) {
|
|
42
|
+
this.edges[from.filename] = [];
|
|
43
|
+
}
|
|
44
|
+
this.edges[from.filename].push(toFilename);
|
|
49
45
|
}
|
|
50
46
|
findTop(filename) {
|
|
51
47
|
const ret = [];
|
|
52
|
-
for (const
|
|
53
|
-
|
|
54
|
-
ret.push(...this.findTop(e.to));
|
|
55
|
-
}
|
|
48
|
+
for (const to of this.edges[filename] || []) {
|
|
49
|
+
ret.push(...this.findTop(to));
|
|
56
50
|
}
|
|
57
51
|
if (ret.length === 0) {
|
|
58
|
-
const found = this.
|
|
52
|
+
const found = this.findVertexByFilename(filename);
|
|
59
53
|
if (found !== undefined) {
|
|
60
54
|
ret.push(found);
|
|
61
55
|
}
|
|
@@ -99,19 +93,23 @@ class IncludeGraph {
|
|
|
99
93
|
this.addVertices();
|
|
100
94
|
for (const o of getABAPObjects(this.reg)) {
|
|
101
95
|
for (const f of o.getABAPFiles()) {
|
|
96
|
+
if (f.getFilename().includes(".prog.screen_") || f.getFilename().includes(".fugr.screen_")) {
|
|
97
|
+
// skip dynpro files
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
102
100
|
for (const s of f.getStatements()) {
|
|
103
101
|
if (s.get() instanceof statements_1.Include) {
|
|
104
|
-
const ifFound = s.concatTokens().toUpperCase().includes("IF FOUND");
|
|
105
102
|
const iexp = s.findFirstExpression(expressions_1.IncludeName);
|
|
106
103
|
if (iexp === undefined) {
|
|
107
104
|
throw new Error("unexpected Include node");
|
|
108
105
|
}
|
|
109
106
|
const name = iexp.getFirstToken().getStr().toUpperCase();
|
|
110
|
-
if (name.match(
|
|
107
|
+
if (name.match(FMXXINCLUDE)) { // function module XX includes, possibily namespaced
|
|
111
108
|
continue;
|
|
112
109
|
}
|
|
113
|
-
const found = this.graph.
|
|
110
|
+
const found = this.graph.findVertexViaIncludename(name);
|
|
114
111
|
if (found === undefined) {
|
|
112
|
+
const ifFound = s.concatTokens().toUpperCase().includes("IF FOUND");
|
|
115
113
|
if (ifFound === false) {
|
|
116
114
|
const issue = issue_1.Issue.atStatement(f, s, "Include " + name + " not found", new check_include_1.CheckInclude().getMetadata().key, severity_1.Severity.Error);
|
|
117
115
|
this.issues.push(issue);
|
|
@@ -131,7 +129,7 @@ class IncludeGraph {
|
|
|
131
129
|
this.findUnusedIncludes();
|
|
132
130
|
}
|
|
133
131
|
findUnusedIncludes() {
|
|
134
|
-
for (const v of this.graph.
|
|
132
|
+
for (const v of Object.values(this.graph.verticesFilenameIndex)) {
|
|
135
133
|
if (v.include === true) {
|
|
136
134
|
if (this.listMainForInclude(v.filename).length === 0) {
|
|
137
135
|
const f = this.reg.getFileByName(v.filename);
|