@abaplint/core 2.113.247 → 2.114.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.
- package/build/abaplint.d.ts +27 -3
- package/build/src/abap/4_file_information/abap_file_information.js +6 -333
- package/build/src/abap/4_file_information/abap_file_information_parser.js +352 -0
- package/build/src/abap/4_file_information/parsed_file_information.js +3 -0
- package/build/src/abap/5_syntax/expressions/select.js +20 -8
- package/build/src/abap/abap_file.js +3 -3
- package/build/src/abap/abap_parser.js +7 -4
- package/build/src/abap/iabap_file.js +3 -0
- package/build/src/objects/email_template.js +21 -0
- package/build/src/objects/function_group.js +2 -0
- package/build/src/objects/index.js +2 -1
- package/build/src/objects/table.js +27 -1
- package/build/src/registry.js +1 -1
- package/build/src/rules/check_include.js +5 -1
- package/build/src/rules/implicit_start_of_selection.js +1 -2
- package/build/src/rules/index.js +1 -0
- package/build/src/rules/index_completely_contained.js +67 -0
- package/build/src/utils/include_graph.js +3 -1
- package/package.json +1 -1
package/build/abaplint.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as LServer from 'vscode-languageserver-types';
|
|
2
2
|
import { WorkspaceEdit } from 'vscode-languageserver-types';
|
|
3
3
|
|
|
4
|
-
export declare class ABAPFile extends AbstractFile {
|
|
4
|
+
export declare class ABAPFile extends AbstractFile implements IABAPFile {
|
|
5
5
|
private readonly tokens;
|
|
6
6
|
private readonly statements;
|
|
7
7
|
private readonly structure;
|
|
@@ -9,8 +9,8 @@ export declare class ABAPFile extends AbstractFile {
|
|
|
9
9
|
private readonly info;
|
|
10
10
|
constructor(file: IFile, tokens: readonly Token[], statements: readonly StatementNode[], structure: StructureNode | undefined, info: IABAPFileInformation);
|
|
11
11
|
getRaw(): string;
|
|
12
|
-
getInfo(): IABAPFileInformation;
|
|
13
12
|
getRawRows(): string[];
|
|
13
|
+
getInfo(): IABAPFileInformation;
|
|
14
14
|
getStructure(): StructureNode | undefined;
|
|
15
15
|
getTokens(withPragmas?: boolean): readonly Token[];
|
|
16
16
|
getStatements(): readonly StatementNode[];
|
|
@@ -2023,6 +2023,15 @@ declare class ElseIf_2 implements IStatement {
|
|
|
2023
2023
|
getMatcher(): IStatementRunnable;
|
|
2024
2024
|
}
|
|
2025
2025
|
|
|
2026
|
+
declare class EmailTemplate extends AbstractObject {
|
|
2027
|
+
getType(): string;
|
|
2028
|
+
getAllowedNaming(): {
|
|
2029
|
+
maxLength: number;
|
|
2030
|
+
allowNamespace: boolean;
|
|
2031
|
+
};
|
|
2032
|
+
getDescription(): string | undefined;
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2026
2035
|
export declare class Empty implements IStatement {
|
|
2027
2036
|
getMatcher(): IStatementRunnable;
|
|
2028
2037
|
}
|
|
@@ -3064,6 +3073,13 @@ declare class HttpService extends AbstractObject {
|
|
|
3064
3073
|
getDescription(): string | undefined;
|
|
3065
3074
|
}
|
|
3066
3075
|
|
|
3076
|
+
export declare interface IABAPFile {
|
|
3077
|
+
getInfo(): IABAPFileInformation;
|
|
3078
|
+
getStructure(): StructureNode | undefined;
|
|
3079
|
+
getTokens(withPragmas?: boolean): readonly Token[];
|
|
3080
|
+
getStatements(): readonly StatementNode[];
|
|
3081
|
+
}
|
|
3082
|
+
|
|
3067
3083
|
declare interface IABAPFileInformation {
|
|
3068
3084
|
listInterfaceDefinitions(): readonly InfoInterfaceDefinition[];
|
|
3069
3085
|
getInterfaceDefinitionByName(name: string): InfoInterfaceDefinition | undefined;
|
|
@@ -5008,7 +5024,6 @@ declare namespace Objects {
|
|
|
5008
5024
|
BRFPlusSystemApplication,
|
|
5009
5025
|
BSPApplication,
|
|
5010
5026
|
BusinessAddInImplementation,
|
|
5011
|
-
CDSEntityBuffer,
|
|
5012
5027
|
BusinessCatalogAppAssignment,
|
|
5013
5028
|
BusinessCatalog,
|
|
5014
5029
|
BusinessConfigurationMaintenanceObject,
|
|
@@ -5017,6 +5032,7 @@ declare namespace Objects {
|
|
|
5017
5032
|
BusinessFunctionSetAssignment,
|
|
5018
5033
|
BusinessObjectModel,
|
|
5019
5034
|
BusinessObjectType,
|
|
5035
|
+
CDSEntityBuffer,
|
|
5020
5036
|
ParsedMetadataExtension,
|
|
5021
5037
|
CDSMetadataExtension,
|
|
5022
5038
|
CDSType,
|
|
@@ -5046,6 +5062,7 @@ declare namespace Objects {
|
|
|
5046
5062
|
EcattTestConfiguration,
|
|
5047
5063
|
EcattTestDataContainer,
|
|
5048
5064
|
EcattTestScript,
|
|
5065
|
+
EmailTemplate,
|
|
5049
5066
|
EnhancementImplementation,
|
|
5050
5067
|
IBadiDefinition,
|
|
5051
5068
|
EnhancementSpot,
|
|
@@ -5142,6 +5159,7 @@ declare namespace Objects {
|
|
|
5142
5159
|
TableType,
|
|
5143
5160
|
EnhancementCategory,
|
|
5144
5161
|
TableCategory,
|
|
5162
|
+
SecondaryIndex,
|
|
5145
5163
|
Table,
|
|
5146
5164
|
TechnicalJobDefinition,
|
|
5147
5165
|
TransactionVariant,
|
|
@@ -5871,6 +5889,11 @@ declare class SearchHelp extends AbstractObject {
|
|
|
5871
5889
|
getDescription(): string | undefined;
|
|
5872
5890
|
}
|
|
5873
5891
|
|
|
5892
|
+
declare type SecondaryIndex = {
|
|
5893
|
+
name: string;
|
|
5894
|
+
fields: string[];
|
|
5895
|
+
};
|
|
5896
|
+
|
|
5874
5897
|
declare class SectionContents implements IStructure {
|
|
5875
5898
|
getMatcher(): IStructureRunnable;
|
|
5876
5899
|
}
|
|
@@ -6963,6 +6986,7 @@ declare class Table extends AbstractObject {
|
|
|
6963
6986
|
private parsedType;
|
|
6964
6987
|
getType(): string;
|
|
6965
6988
|
getDescription(): string | undefined;
|
|
6989
|
+
getSecondaryIndexes(): SecondaryIndex[] | undefined;
|
|
6966
6990
|
getAllowedNaming(): IAllowedNaming;
|
|
6967
6991
|
setDirty(): void;
|
|
6968
6992
|
listKeys(reg: IRegistry): string[];
|
|
@@ -1,27 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ABAPFileInformation = void 0;
|
|
4
|
-
const Structures = require("../3_structures/structures");
|
|
5
|
-
const Expressions = require("../2_statements/expressions");
|
|
6
|
-
const Statements = require("../2_statements/statements");
|
|
7
|
-
const _abap_file_information_1 = require("./_abap_file_information");
|
|
8
|
-
const _identifier_1 = require("./_identifier");
|
|
9
|
-
const Tokens = require("../1_lexer/tokens");
|
|
10
|
-
const visibility_1 = require("./visibility");
|
|
11
4
|
class ABAPFileInformation {
|
|
12
|
-
constructor(
|
|
13
|
-
this.
|
|
14
|
-
this.implementations = [];
|
|
15
|
-
this.interfaces = [];
|
|
16
|
-
this.classes = [];
|
|
17
|
-
this.filename = filename;
|
|
18
|
-
this.parse(structure);
|
|
5
|
+
constructor(parsed) {
|
|
6
|
+
this.parsed = parsed;
|
|
19
7
|
}
|
|
20
8
|
listClassImplementations() {
|
|
21
|
-
return this.implementations;
|
|
9
|
+
return this.parsed.implementations;
|
|
22
10
|
}
|
|
23
11
|
listInterfaceDefinitions() {
|
|
24
|
-
return this.interfaces;
|
|
12
|
+
return this.parsed.interfaces;
|
|
25
13
|
}
|
|
26
14
|
getInterfaceDefinitionByName(name) {
|
|
27
15
|
const upper = name.toUpperCase();
|
|
@@ -33,7 +21,7 @@ class ABAPFileInformation {
|
|
|
33
21
|
return undefined;
|
|
34
22
|
}
|
|
35
23
|
listClassDefinitions() {
|
|
36
|
-
return this.classes;
|
|
24
|
+
return this.parsed.classes;
|
|
37
25
|
}
|
|
38
26
|
getClassDefinitionByName(name) {
|
|
39
27
|
const upper = name.toUpperCase();
|
|
@@ -54,322 +42,7 @@ class ABAPFileInformation {
|
|
|
54
42
|
return undefined;
|
|
55
43
|
}
|
|
56
44
|
listFormDefinitions() {
|
|
57
|
-
return this.forms;
|
|
58
|
-
}
|
|
59
|
-
///////////////////////
|
|
60
|
-
parse(structure) {
|
|
61
|
-
var _a;
|
|
62
|
-
if (structure === undefined) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
this.parseClasses(structure);
|
|
66
|
-
this.parseInterfaces(structure);
|
|
67
|
-
for (const found of structure.findAllStructures(Structures.ClassImplementation)) {
|
|
68
|
-
const methods = [];
|
|
69
|
-
for (const method of found.findAllStructures(Structures.Method)) {
|
|
70
|
-
const methodName = (_a = method.findFirstExpression(Expressions.MethodName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
71
|
-
if (methodName) {
|
|
72
|
-
methods.push(new _identifier_1.Identifier(methodName, this.filename));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const name = found.findFirstStatement(Statements.ClassImplementation).findFirstExpression(Expressions.ClassName).getFirstToken();
|
|
76
|
-
this.implementations.push({
|
|
77
|
-
name: name.getStr(),
|
|
78
|
-
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
79
|
-
methods,
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
for (const statement of structure.findAllStructures(Structures.Form)) {
|
|
83
|
-
// FORMs can contain a dash in the name
|
|
84
|
-
const pos = statement.findFirstExpression(Expressions.FormName).getFirstToken().getStart();
|
|
85
|
-
const name = statement.findFirstExpression(Expressions.FormName).concatTokens();
|
|
86
|
-
const nameToken = new Tokens.Identifier(pos, name);
|
|
87
|
-
this.forms.push({
|
|
88
|
-
name: nameToken.getStr(),
|
|
89
|
-
identifier: new _identifier_1.Identifier(nameToken, this.filename),
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
parseInterfaces(structure) {
|
|
94
|
-
for (const found of structure.findDirectStructures(Structures.Interface)) {
|
|
95
|
-
const i = found.findFirstStatement(Statements.Interface);
|
|
96
|
-
if (i === undefined) {
|
|
97
|
-
throw new Error("Interface expected, parseInterfaces");
|
|
98
|
-
}
|
|
99
|
-
const interfaceName = i.findDirectExpression(Expressions.InterfaceName).getFirstToken();
|
|
100
|
-
const methods = this.parseMethodDefinition(found, visibility_1.Visibility.Public);
|
|
101
|
-
const attributes = this.parseAttributes(found, visibility_1.Visibility.Public);
|
|
102
|
-
const aliases = this.parseAliases(found, visibility_1.Visibility.Public);
|
|
103
|
-
const constants = this.parseConstants(found, visibility_1.Visibility.Public);
|
|
104
|
-
const g = i.findDirectExpression(Expressions.ClassGlobal);
|
|
105
|
-
this.interfaces.push({
|
|
106
|
-
name: interfaceName.getStr(),
|
|
107
|
-
identifier: new _identifier_1.Identifier(interfaceName, this.filename),
|
|
108
|
-
isLocal: g === undefined,
|
|
109
|
-
isGlobal: g !== undefined,
|
|
110
|
-
interfaces: this.getImplementing(found),
|
|
111
|
-
aliases,
|
|
112
|
-
methods,
|
|
113
|
-
constants,
|
|
114
|
-
attributes,
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
parseClasses(structure) {
|
|
119
|
-
var _a;
|
|
120
|
-
for (const found of structure.findAllStructures(Structures.ClassDefinition)) {
|
|
121
|
-
const className = found.findFirstStatement(Statements.ClassDefinition).findFirstExpression(Expressions.ClassName).getFirstToken();
|
|
122
|
-
const methods = this.parseMethodDefinition(found.findFirstStructure(Structures.PublicSection), visibility_1.Visibility.Public);
|
|
123
|
-
methods.push(...this.parseMethodDefinition(found.findFirstStructure(Structures.ProtectedSection), visibility_1.Visibility.Protected));
|
|
124
|
-
methods.push(...this.parseMethodDefinition(found.findFirstStructure(Structures.PrivateSection), visibility_1.Visibility.Private));
|
|
125
|
-
const attributes = this.parseAttributes(found.findFirstStructure(Structures.PublicSection), visibility_1.Visibility.Public);
|
|
126
|
-
attributes.push(...this.parseAttributes(found.findFirstStructure(Structures.ProtectedSection), visibility_1.Visibility.Protected));
|
|
127
|
-
attributes.push(...this.parseAttributes(found.findFirstStructure(Structures.PrivateSection), visibility_1.Visibility.Private));
|
|
128
|
-
const aliases = this.parseAliases(found.findFirstStructure(Structures.PublicSection), visibility_1.Visibility.Public);
|
|
129
|
-
aliases.push(...this.parseAliases(found.findFirstStructure(Structures.ProtectedSection), visibility_1.Visibility.Protected));
|
|
130
|
-
aliases.push(...this.parseAliases(found.findFirstStructure(Structures.PrivateSection), visibility_1.Visibility.Private));
|
|
131
|
-
const constants = this.parseConstants(found.findFirstStructure(Structures.PublicSection), visibility_1.Visibility.Public);
|
|
132
|
-
constants.push(...this.parseConstants(found.findFirstStructure(Structures.ProtectedSection), visibility_1.Visibility.Protected));
|
|
133
|
-
constants.push(...this.parseConstants(found.findFirstStructure(Structures.PrivateSection), visibility_1.Visibility.Private));
|
|
134
|
-
const superClassName = (_a = found.findFirstExpression(Expressions.SuperClassName)) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr();
|
|
135
|
-
const containsGlobal = found.findFirstExpression(Expressions.ClassGlobal);
|
|
136
|
-
const cdef = found.findFirstStatement(Statements.ClassDefinition);
|
|
137
|
-
const concat = (cdef === null || cdef === void 0 ? void 0 : cdef.concatTokens().toUpperCase()) || "";
|
|
138
|
-
let riskLevel;
|
|
139
|
-
if (concat.includes("RISK LEVEL CRITICAL")) {
|
|
140
|
-
riskLevel = _abap_file_information_1.RiskLevel.critical;
|
|
141
|
-
}
|
|
142
|
-
else if (concat.includes("RISK LEVEL DANGEROUS")) {
|
|
143
|
-
riskLevel = _abap_file_information_1.RiskLevel.dangerous;
|
|
144
|
-
}
|
|
145
|
-
else if (concat.includes("RISK LEVEL HARMLESS")) {
|
|
146
|
-
riskLevel = _abap_file_information_1.RiskLevel.harmless;
|
|
147
|
-
}
|
|
148
|
-
let duration;
|
|
149
|
-
if (concat.includes("DURATION SHORT")) {
|
|
150
|
-
duration = _abap_file_information_1.Duration.short;
|
|
151
|
-
}
|
|
152
|
-
else if (concat.includes("DURATION LONG")) {
|
|
153
|
-
duration = _abap_file_information_1.Duration.long;
|
|
154
|
-
}
|
|
155
|
-
else if (concat.includes("DURATION MEDIUM")) {
|
|
156
|
-
duration = _abap_file_information_1.Duration.medium;
|
|
157
|
-
}
|
|
158
|
-
this.classes.push({
|
|
159
|
-
name: className.getStr(),
|
|
160
|
-
identifier: new _identifier_1.Identifier(className, this.filename),
|
|
161
|
-
isLocal: containsGlobal === undefined,
|
|
162
|
-
isGlobal: containsGlobal !== undefined,
|
|
163
|
-
methods,
|
|
164
|
-
superClassName,
|
|
165
|
-
interfaces: this.getImplementing(found),
|
|
166
|
-
isForTesting: concat.includes(" FOR TESTING"),
|
|
167
|
-
duration,
|
|
168
|
-
riskLevel,
|
|
169
|
-
isAbstract: (cdef === null || cdef === void 0 ? void 0 : cdef.findDirectTokenByText("ABSTRACT")) !== undefined,
|
|
170
|
-
isSharedMemory: concat.includes(" SHARED MEMORY ENABLED"),
|
|
171
|
-
isFinal: found.findFirstExpression(Expressions.ClassFinal) !== undefined,
|
|
172
|
-
aliases,
|
|
173
|
-
attributes,
|
|
174
|
-
constants,
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
///////////////////
|
|
179
|
-
getImplementing(input) {
|
|
180
|
-
const ret = [];
|
|
181
|
-
for (const node of input.findAllStatements(Statements.InterfaceDef)) {
|
|
182
|
-
const abstract = node.findDirectExpression(Expressions.AbstractMethods);
|
|
183
|
-
const abstractMethods = [];
|
|
184
|
-
if (abstract) {
|
|
185
|
-
for (const m of abstract.findDirectExpressions(Expressions.MethodName)) {
|
|
186
|
-
abstractMethods.push(m.concatTokens().toUpperCase());
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
const final = node.findDirectExpression(Expressions.FinalMethods);
|
|
190
|
-
const finalMethods = [];
|
|
191
|
-
if (final) {
|
|
192
|
-
for (const m of final.findDirectExpressions(Expressions.MethodName)) {
|
|
193
|
-
finalMethods.push(m.concatTokens().toUpperCase());
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
const concat = node.concatTokens().toUpperCase();
|
|
197
|
-
const allAbstract = concat.includes(" ALL METHODS ABSTRACT");
|
|
198
|
-
const partial = concat.includes(" PARTIALLY IMPLEMENTED");
|
|
199
|
-
const name = node.findFirstExpression(Expressions.InterfaceName).getFirstToken().getStr().toUpperCase();
|
|
200
|
-
ret.push({
|
|
201
|
-
name,
|
|
202
|
-
partial,
|
|
203
|
-
allAbstract,
|
|
204
|
-
abstractMethods,
|
|
205
|
-
finalMethods,
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
return ret;
|
|
209
|
-
}
|
|
210
|
-
parseAliases(node, visibility) {
|
|
211
|
-
if (node === undefined) {
|
|
212
|
-
return [];
|
|
213
|
-
}
|
|
214
|
-
const ret = [];
|
|
215
|
-
for (const a of node.findAllStatements(Statements.Aliases)) {
|
|
216
|
-
const name = a.findFirstExpression(Expressions.SimpleName).getFirstToken();
|
|
217
|
-
const comp = a.findFirstExpression(Expressions.Field).getFirstToken();
|
|
218
|
-
ret.push({
|
|
219
|
-
name: name.getStr(),
|
|
220
|
-
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
221
|
-
visibility,
|
|
222
|
-
component: comp.getStr(),
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
return ret;
|
|
226
|
-
}
|
|
227
|
-
parseConstants(node, visibility) {
|
|
228
|
-
var _a, _b;
|
|
229
|
-
if (node === undefined) {
|
|
230
|
-
return [];
|
|
231
|
-
}
|
|
232
|
-
const results = [];
|
|
233
|
-
for (const constant of node.findAllStatements(Statements.Constant)) {
|
|
234
|
-
const name = constant.findFirstExpression(Expressions.DefinitionName).getFirstToken();
|
|
235
|
-
const typeName = constant.findFirstExpression(Expressions.TypeName);
|
|
236
|
-
// VALUE `const_value` -> `const_value`
|
|
237
|
-
const literal = (_b = (_a = constant.findFirstExpression(Expressions.Value)) === null || _a === void 0 ? void 0 : _a.getTokens()[1].getStr()) !== null && _b !== void 0 ? _b : "``";
|
|
238
|
-
// `const_value` -> const_value
|
|
239
|
-
const value = literal.slice(1, (literal === null || literal === void 0 ? void 0 : literal.length) - 1);
|
|
240
|
-
results.push({
|
|
241
|
-
name: name.getStr(),
|
|
242
|
-
typeName: typeName ? typeName.getFirstToken().getStr() : "",
|
|
243
|
-
value: value,
|
|
244
|
-
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
245
|
-
visibility,
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
return results;
|
|
249
|
-
}
|
|
250
|
-
parseAttributes(node, visibility) {
|
|
251
|
-
if (node === undefined) {
|
|
252
|
-
return [];
|
|
253
|
-
}
|
|
254
|
-
const contents = node.findFirstStructure(Structures.SectionContents);
|
|
255
|
-
if (contents === undefined) {
|
|
256
|
-
return [];
|
|
257
|
-
}
|
|
258
|
-
const ret = [];
|
|
259
|
-
for (const d of contents.findDirectStatements(Statements.Data)) {
|
|
260
|
-
const name = d.findFirstExpression(Expressions.DefinitionName).getFirstToken();
|
|
261
|
-
ret.push({
|
|
262
|
-
name: name.getStr(),
|
|
263
|
-
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
264
|
-
level: _abap_file_information_1.AttributeLevel.Instance,
|
|
265
|
-
readOnly: d.concatTokens().toUpperCase().includes(" READ-ONLY"),
|
|
266
|
-
visibility,
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
for (const d of contents.findDirectStatements(Statements.ClassData)) {
|
|
270
|
-
const name = d.findFirstExpression(Expressions.DefinitionName).getFirstToken();
|
|
271
|
-
ret.push({
|
|
272
|
-
name: name.getStr(),
|
|
273
|
-
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
274
|
-
level: _abap_file_information_1.AttributeLevel.Static,
|
|
275
|
-
readOnly: d.concatTokens().toUpperCase().includes(" READ-ONLY"),
|
|
276
|
-
visibility,
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
for (const d of contents.findDirectStatements(Statements.Constant)) {
|
|
280
|
-
const name = d.findFirstExpression(Expressions.DefinitionName).getFirstToken();
|
|
281
|
-
ret.push({
|
|
282
|
-
name: name.getStr(),
|
|
283
|
-
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
284
|
-
level: _abap_file_information_1.AttributeLevel.Constant,
|
|
285
|
-
readOnly: true,
|
|
286
|
-
visibility,
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
return ret;
|
|
290
|
-
}
|
|
291
|
-
parseMethodDefinition(node, visibility) {
|
|
292
|
-
var _a;
|
|
293
|
-
if (node === undefined) {
|
|
294
|
-
return [];
|
|
295
|
-
}
|
|
296
|
-
const methods = [];
|
|
297
|
-
for (const def of node.findAllStatements(Statements.MethodDef)) {
|
|
298
|
-
const methodName = (_a = def.findDirectExpression(Expressions.MethodName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
299
|
-
if (methodName === undefined) {
|
|
300
|
-
continue;
|
|
301
|
-
}
|
|
302
|
-
const parameters = this.parseMethodParameters(def);
|
|
303
|
-
methods.push({
|
|
304
|
-
name: methodName.getStr(),
|
|
305
|
-
identifier: new _identifier_1.Identifier(methodName, this.filename),
|
|
306
|
-
isRedefinition: def.findDirectExpression(Expressions.Redefinition) !== undefined,
|
|
307
|
-
isForTesting: def.concatTokens().toUpperCase().includes(" FOR TESTING"),
|
|
308
|
-
isFinal: def.concatTokens().toUpperCase().includes(" FINAL"),
|
|
309
|
-
isAbstract: def.findDirectExpression(Expressions.Abstract) !== undefined,
|
|
310
|
-
isEventHandler: def.findDirectExpression(Expressions.EventHandler) !== undefined,
|
|
311
|
-
visibility,
|
|
312
|
-
parameters,
|
|
313
|
-
exceptions: [], // todo
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
return methods;
|
|
317
|
-
}
|
|
318
|
-
// todo, refactor this method, it is too long
|
|
319
|
-
parseMethodParameters(node) {
|
|
320
|
-
var _a, _b, _c, _d;
|
|
321
|
-
const ret = [];
|
|
322
|
-
const importing = node.findFirstExpression(Expressions.MethodDefImporting);
|
|
323
|
-
if (importing) {
|
|
324
|
-
for (const param of importing.findAllExpressions(Expressions.MethodParam)) {
|
|
325
|
-
const name = (_a = param.findDirectExpression(Expressions.MethodParamName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
326
|
-
if (name) {
|
|
327
|
-
ret.push({
|
|
328
|
-
name: name.getStr().replace("!", ""),
|
|
329
|
-
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
330
|
-
direction: _abap_file_information_1.MethodParameterDirection.Importing,
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
const exporting = node.findFirstExpression(Expressions.MethodDefExporting);
|
|
336
|
-
if (exporting) {
|
|
337
|
-
for (const param of exporting.findAllExpressions(Expressions.MethodParam)) {
|
|
338
|
-
const name = (_b = param.findDirectExpression(Expressions.MethodParamName)) === null || _b === void 0 ? void 0 : _b.getFirstToken();
|
|
339
|
-
if (name) {
|
|
340
|
-
ret.push({
|
|
341
|
-
name: name.getStr().replace("!", ""),
|
|
342
|
-
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
343
|
-
direction: _abap_file_information_1.MethodParameterDirection.Exporting,
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
const changing = node.findFirstExpression(Expressions.MethodDefChanging);
|
|
349
|
-
if (changing) {
|
|
350
|
-
for (const param of changing.findAllExpressions(Expressions.MethodParam)) {
|
|
351
|
-
const name = (_c = param.findDirectExpression(Expressions.MethodParamName)) === null || _c === void 0 ? void 0 : _c.getFirstToken();
|
|
352
|
-
if (name) {
|
|
353
|
-
ret.push({
|
|
354
|
-
name: name.getStr().replace("!", ""),
|
|
355
|
-
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
356
|
-
direction: _abap_file_information_1.MethodParameterDirection.Changing,
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
const returning = node.findFirstExpression(Expressions.MethodDefReturning);
|
|
362
|
-
if (returning) {
|
|
363
|
-
const name = (_d = returning.findDirectExpression(Expressions.MethodParamName)) === null || _d === void 0 ? void 0 : _d.getFirstToken();
|
|
364
|
-
if (name) {
|
|
365
|
-
ret.push({
|
|
366
|
-
name: name.getStr().replace("!", ""),
|
|
367
|
-
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
368
|
-
direction: _abap_file_information_1.MethodParameterDirection.Returning,
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
return ret;
|
|
45
|
+
return this.parsed.forms;
|
|
373
46
|
}
|
|
374
47
|
}
|
|
375
48
|
exports.ABAPFileInformation = ABAPFileInformation;
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ABAPFileInformationParser = void 0;
|
|
4
|
+
const Structures = require("../3_structures/structures");
|
|
5
|
+
const Expressions = require("../2_statements/expressions");
|
|
6
|
+
const Statements = require("../2_statements/statements");
|
|
7
|
+
const _identifier_1 = require("./_identifier");
|
|
8
|
+
const Tokens = require("../1_lexer/tokens");
|
|
9
|
+
const visibility_1 = require("./visibility");
|
|
10
|
+
const _abap_file_information_1 = require("./_abap_file_information");
|
|
11
|
+
class ABAPFileInformationParser {
|
|
12
|
+
constructor(filename) {
|
|
13
|
+
this.filename = filename;
|
|
14
|
+
}
|
|
15
|
+
parse(structure) {
|
|
16
|
+
const result = {
|
|
17
|
+
interfaces: [],
|
|
18
|
+
classes: [],
|
|
19
|
+
forms: [],
|
|
20
|
+
implementations: [],
|
|
21
|
+
};
|
|
22
|
+
if (structure === undefined) {
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
result.classes = this.parseClasses(structure);
|
|
26
|
+
result.interfaces = this.parseInterfaces(structure);
|
|
27
|
+
result.implementations = this.parseClassImplementations(structure);
|
|
28
|
+
result.forms = this.parseForms(structure);
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
parseClassImplementations(structure) {
|
|
32
|
+
var _a;
|
|
33
|
+
const implementations = [];
|
|
34
|
+
for (const found of structure.findAllStructures(Structures.ClassImplementation)) {
|
|
35
|
+
const methods = [];
|
|
36
|
+
for (const method of found.findAllStructures(Structures.Method)) {
|
|
37
|
+
const methodName = (_a = method.findFirstExpression(Expressions.MethodName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
38
|
+
if (methodName) {
|
|
39
|
+
methods.push(new _identifier_1.Identifier(methodName, this.filename));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const name = found.findFirstStatement(Statements.ClassImplementation).findFirstExpression(Expressions.ClassName).getFirstToken();
|
|
43
|
+
implementations.push({
|
|
44
|
+
name: name.getStr(),
|
|
45
|
+
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
46
|
+
methods,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return implementations;
|
|
50
|
+
}
|
|
51
|
+
parseForms(structure) {
|
|
52
|
+
const forms = [];
|
|
53
|
+
for (const statement of structure.findAllStructures(Structures.Form)) {
|
|
54
|
+
// FORMs can contain a dash in the name
|
|
55
|
+
const pos = statement.findFirstExpression(Expressions.FormName).getFirstToken().getStart();
|
|
56
|
+
const name = statement.findFirstExpression(Expressions.FormName).concatTokens();
|
|
57
|
+
const nameToken = new Tokens.Identifier(pos, name);
|
|
58
|
+
forms.push({
|
|
59
|
+
name: nameToken.getStr(),
|
|
60
|
+
identifier: new _identifier_1.Identifier(nameToken, this.filename),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return forms;
|
|
64
|
+
}
|
|
65
|
+
parseInterfaces(structure) {
|
|
66
|
+
const interfaces = [];
|
|
67
|
+
for (const found of structure.findDirectStructures(Structures.Interface)) {
|
|
68
|
+
const i = found.findFirstStatement(Statements.Interface);
|
|
69
|
+
if (i === undefined) {
|
|
70
|
+
throw new Error("Interface expected, parseInterfaces");
|
|
71
|
+
}
|
|
72
|
+
const interfaceName = i.findDirectExpression(Expressions.InterfaceName).getFirstToken();
|
|
73
|
+
const methods = this.parseMethodDefinition(found, visibility_1.Visibility.Public);
|
|
74
|
+
const attributes = this.parseAttributes(found, visibility_1.Visibility.Public);
|
|
75
|
+
const aliases = this.parseAliases(found, visibility_1.Visibility.Public);
|
|
76
|
+
const constants = this.parseConstants(found, visibility_1.Visibility.Public);
|
|
77
|
+
const g = i.findDirectExpression(Expressions.ClassGlobal);
|
|
78
|
+
interfaces.push({
|
|
79
|
+
name: interfaceName.getStr(),
|
|
80
|
+
identifier: new _identifier_1.Identifier(interfaceName, this.filename),
|
|
81
|
+
isLocal: g === undefined,
|
|
82
|
+
isGlobal: g !== undefined,
|
|
83
|
+
interfaces: this.getImplementing(found),
|
|
84
|
+
aliases,
|
|
85
|
+
methods,
|
|
86
|
+
constants,
|
|
87
|
+
attributes,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return interfaces;
|
|
91
|
+
}
|
|
92
|
+
parseClasses(structure) {
|
|
93
|
+
var _a;
|
|
94
|
+
const classes = [];
|
|
95
|
+
for (const found of structure.findAllStructures(Structures.ClassDefinition)) {
|
|
96
|
+
const className = found.findFirstStatement(Statements.ClassDefinition).findFirstExpression(Expressions.ClassName).getFirstToken();
|
|
97
|
+
const methods = this.parseMethodDefinition(found.findFirstStructure(Structures.PublicSection), visibility_1.Visibility.Public);
|
|
98
|
+
methods.push(...this.parseMethodDefinition(found.findFirstStructure(Structures.ProtectedSection), visibility_1.Visibility.Protected));
|
|
99
|
+
methods.push(...this.parseMethodDefinition(found.findFirstStructure(Structures.PrivateSection), visibility_1.Visibility.Private));
|
|
100
|
+
const attributes = this.parseAttributes(found.findFirstStructure(Structures.PublicSection), visibility_1.Visibility.Public);
|
|
101
|
+
attributes.push(...this.parseAttributes(found.findFirstStructure(Structures.ProtectedSection), visibility_1.Visibility.Protected));
|
|
102
|
+
attributes.push(...this.parseAttributes(found.findFirstStructure(Structures.PrivateSection), visibility_1.Visibility.Private));
|
|
103
|
+
const aliases = this.parseAliases(found.findFirstStructure(Structures.PublicSection), visibility_1.Visibility.Public);
|
|
104
|
+
aliases.push(...this.parseAliases(found.findFirstStructure(Structures.ProtectedSection), visibility_1.Visibility.Protected));
|
|
105
|
+
aliases.push(...this.parseAliases(found.findFirstStructure(Structures.PrivateSection), visibility_1.Visibility.Private));
|
|
106
|
+
const constants = this.parseConstants(found.findFirstStructure(Structures.PublicSection), visibility_1.Visibility.Public);
|
|
107
|
+
constants.push(...this.parseConstants(found.findFirstStructure(Structures.ProtectedSection), visibility_1.Visibility.Protected));
|
|
108
|
+
constants.push(...this.parseConstants(found.findFirstStructure(Structures.PrivateSection), visibility_1.Visibility.Private));
|
|
109
|
+
const superClassName = (_a = found.findFirstExpression(Expressions.SuperClassName)) === null || _a === void 0 ? void 0 : _a.getFirstToken().getStr();
|
|
110
|
+
const containsGlobal = found.findFirstExpression(Expressions.ClassGlobal);
|
|
111
|
+
const cdef = found.findFirstStatement(Statements.ClassDefinition);
|
|
112
|
+
const concat = (cdef === null || cdef === void 0 ? void 0 : cdef.concatTokens().toUpperCase()) || "";
|
|
113
|
+
let riskLevel;
|
|
114
|
+
if (concat.includes("RISK LEVEL CRITICAL")) {
|
|
115
|
+
riskLevel = _abap_file_information_1.RiskLevel.critical;
|
|
116
|
+
}
|
|
117
|
+
else if (concat.includes("RISK LEVEL DANGEROUS")) {
|
|
118
|
+
riskLevel = _abap_file_information_1.RiskLevel.dangerous;
|
|
119
|
+
}
|
|
120
|
+
else if (concat.includes("RISK LEVEL HARMLESS")) {
|
|
121
|
+
riskLevel = _abap_file_information_1.RiskLevel.harmless;
|
|
122
|
+
}
|
|
123
|
+
let duration;
|
|
124
|
+
if (concat.includes("DURATION SHORT")) {
|
|
125
|
+
duration = _abap_file_information_1.Duration.short;
|
|
126
|
+
}
|
|
127
|
+
else if (concat.includes("DURATION LONG")) {
|
|
128
|
+
duration = _abap_file_information_1.Duration.long;
|
|
129
|
+
}
|
|
130
|
+
else if (concat.includes("DURATION MEDIUM")) {
|
|
131
|
+
duration = _abap_file_information_1.Duration.medium;
|
|
132
|
+
}
|
|
133
|
+
classes.push({
|
|
134
|
+
name: className.getStr(),
|
|
135
|
+
identifier: new _identifier_1.Identifier(className, this.filename),
|
|
136
|
+
isLocal: containsGlobal === undefined,
|
|
137
|
+
isGlobal: containsGlobal !== undefined,
|
|
138
|
+
methods,
|
|
139
|
+
superClassName,
|
|
140
|
+
interfaces: this.getImplementing(found),
|
|
141
|
+
isForTesting: concat.includes(" FOR TESTING"),
|
|
142
|
+
duration,
|
|
143
|
+
riskLevel,
|
|
144
|
+
isAbstract: (cdef === null || cdef === void 0 ? void 0 : cdef.findDirectTokenByText("ABSTRACT")) !== undefined,
|
|
145
|
+
isSharedMemory: concat.includes(" SHARED MEMORY ENABLED"),
|
|
146
|
+
isFinal: found.findFirstExpression(Expressions.ClassFinal) !== undefined,
|
|
147
|
+
aliases,
|
|
148
|
+
attributes,
|
|
149
|
+
constants,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return classes;
|
|
153
|
+
}
|
|
154
|
+
///////////////////
|
|
155
|
+
getImplementing(input) {
|
|
156
|
+
const ret = [];
|
|
157
|
+
for (const node of input.findAllStatements(Statements.InterfaceDef)) {
|
|
158
|
+
const abstract = node.findDirectExpression(Expressions.AbstractMethods);
|
|
159
|
+
const abstractMethods = [];
|
|
160
|
+
if (abstract) {
|
|
161
|
+
for (const m of abstract.findDirectExpressions(Expressions.MethodName)) {
|
|
162
|
+
abstractMethods.push(m.concatTokens().toUpperCase());
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const final = node.findDirectExpression(Expressions.FinalMethods);
|
|
166
|
+
const finalMethods = [];
|
|
167
|
+
if (final) {
|
|
168
|
+
for (const m of final.findDirectExpressions(Expressions.MethodName)) {
|
|
169
|
+
finalMethods.push(m.concatTokens().toUpperCase());
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const concat = node.concatTokens().toUpperCase();
|
|
173
|
+
const allAbstract = concat.includes(" ALL METHODS ABSTRACT");
|
|
174
|
+
const partial = concat.includes(" PARTIALLY IMPLEMENTED");
|
|
175
|
+
const name = node.findFirstExpression(Expressions.InterfaceName).getFirstToken().getStr().toUpperCase();
|
|
176
|
+
ret.push({
|
|
177
|
+
name,
|
|
178
|
+
partial,
|
|
179
|
+
allAbstract,
|
|
180
|
+
abstractMethods,
|
|
181
|
+
finalMethods,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
return ret;
|
|
185
|
+
}
|
|
186
|
+
parseAliases(node, visibility) {
|
|
187
|
+
if (node === undefined) {
|
|
188
|
+
return [];
|
|
189
|
+
}
|
|
190
|
+
const ret = [];
|
|
191
|
+
for (const a of node.findAllStatements(Statements.Aliases)) {
|
|
192
|
+
const name = a.findFirstExpression(Expressions.SimpleName).getFirstToken();
|
|
193
|
+
const comp = a.findFirstExpression(Expressions.Field).getFirstToken();
|
|
194
|
+
ret.push({
|
|
195
|
+
name: name.getStr(),
|
|
196
|
+
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
197
|
+
visibility,
|
|
198
|
+
component: comp.getStr(),
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
return ret;
|
|
202
|
+
}
|
|
203
|
+
parseConstants(node, visibility) {
|
|
204
|
+
var _a, _b;
|
|
205
|
+
if (node === undefined) {
|
|
206
|
+
return [];
|
|
207
|
+
}
|
|
208
|
+
const results = [];
|
|
209
|
+
for (const constant of node.findAllStatements(Statements.Constant)) {
|
|
210
|
+
const name = constant.findFirstExpression(Expressions.DefinitionName).getFirstToken();
|
|
211
|
+
const typeName = constant.findFirstExpression(Expressions.TypeName);
|
|
212
|
+
// VALUE `const_value` -> `const_value`
|
|
213
|
+
const literal = (_b = (_a = constant.findFirstExpression(Expressions.Value)) === null || _a === void 0 ? void 0 : _a.getTokens()[1].getStr()) !== null && _b !== void 0 ? _b : "``";
|
|
214
|
+
// `const_value` -> const_value
|
|
215
|
+
const value = literal.slice(1, (literal === null || literal === void 0 ? void 0 : literal.length) - 1);
|
|
216
|
+
results.push({
|
|
217
|
+
name: name.getStr(),
|
|
218
|
+
typeName: typeName ? typeName.getFirstToken().getStr() : "",
|
|
219
|
+
value: value,
|
|
220
|
+
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
221
|
+
visibility,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
return results;
|
|
225
|
+
}
|
|
226
|
+
parseAttributes(node, visibility) {
|
|
227
|
+
if (node === undefined) {
|
|
228
|
+
return [];
|
|
229
|
+
}
|
|
230
|
+
const contents = node.findFirstStructure(Structures.SectionContents);
|
|
231
|
+
if (contents === undefined) {
|
|
232
|
+
return [];
|
|
233
|
+
}
|
|
234
|
+
const ret = [];
|
|
235
|
+
for (const d of contents.findDirectStatements(Statements.Data)) {
|
|
236
|
+
const name = d.findFirstExpression(Expressions.DefinitionName).getFirstToken();
|
|
237
|
+
ret.push({
|
|
238
|
+
name: name.getStr(),
|
|
239
|
+
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
240
|
+
level: _abap_file_information_1.AttributeLevel.Instance,
|
|
241
|
+
readOnly: d.concatTokens().toUpperCase().includes(" READ-ONLY"),
|
|
242
|
+
visibility,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
for (const d of contents.findDirectStatements(Statements.ClassData)) {
|
|
246
|
+
const name = d.findFirstExpression(Expressions.DefinitionName).getFirstToken();
|
|
247
|
+
ret.push({
|
|
248
|
+
name: name.getStr(),
|
|
249
|
+
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
250
|
+
level: _abap_file_information_1.AttributeLevel.Static,
|
|
251
|
+
readOnly: d.concatTokens().toUpperCase().includes(" READ-ONLY"),
|
|
252
|
+
visibility,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
for (const d of contents.findDirectStatements(Statements.Constant)) {
|
|
256
|
+
const name = d.findFirstExpression(Expressions.DefinitionName).getFirstToken();
|
|
257
|
+
ret.push({
|
|
258
|
+
name: name.getStr(),
|
|
259
|
+
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
260
|
+
level: _abap_file_information_1.AttributeLevel.Constant,
|
|
261
|
+
readOnly: true,
|
|
262
|
+
visibility,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
return ret;
|
|
266
|
+
}
|
|
267
|
+
parseMethodDefinition(node, visibility) {
|
|
268
|
+
var _a;
|
|
269
|
+
if (node === undefined) {
|
|
270
|
+
return [];
|
|
271
|
+
}
|
|
272
|
+
const methods = [];
|
|
273
|
+
for (const def of node.findAllStatements(Statements.MethodDef)) {
|
|
274
|
+
const methodName = (_a = def.findDirectExpression(Expressions.MethodName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
275
|
+
if (methodName === undefined) {
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
const parameters = this.parseMethodParameters(def);
|
|
279
|
+
methods.push({
|
|
280
|
+
name: methodName.getStr(),
|
|
281
|
+
identifier: new _identifier_1.Identifier(methodName, this.filename),
|
|
282
|
+
isRedefinition: def.findDirectExpression(Expressions.Redefinition) !== undefined,
|
|
283
|
+
isForTesting: def.concatTokens().toUpperCase().includes(" FOR TESTING"),
|
|
284
|
+
isFinal: def.concatTokens().toUpperCase().includes(" FINAL"),
|
|
285
|
+
isAbstract: def.findDirectExpression(Expressions.Abstract) !== undefined,
|
|
286
|
+
isEventHandler: def.findDirectExpression(Expressions.EventHandler) !== undefined,
|
|
287
|
+
visibility,
|
|
288
|
+
parameters,
|
|
289
|
+
exceptions: [], // todo
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
return methods;
|
|
293
|
+
}
|
|
294
|
+
// todo, refactor this method, it is too long
|
|
295
|
+
parseMethodParameters(node) {
|
|
296
|
+
var _a, _b, _c, _d;
|
|
297
|
+
const ret = [];
|
|
298
|
+
const importing = node.findFirstExpression(Expressions.MethodDefImporting);
|
|
299
|
+
if (importing) {
|
|
300
|
+
for (const param of importing.findAllExpressions(Expressions.MethodParam)) {
|
|
301
|
+
const name = (_a = param.findDirectExpression(Expressions.MethodParamName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
|
|
302
|
+
if (name) {
|
|
303
|
+
ret.push({
|
|
304
|
+
name: name.getStr().replace("!", ""),
|
|
305
|
+
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
306
|
+
direction: _abap_file_information_1.MethodParameterDirection.Importing,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
const exporting = node.findFirstExpression(Expressions.MethodDefExporting);
|
|
312
|
+
if (exporting) {
|
|
313
|
+
for (const param of exporting.findAllExpressions(Expressions.MethodParam)) {
|
|
314
|
+
const name = (_b = param.findDirectExpression(Expressions.MethodParamName)) === null || _b === void 0 ? void 0 : _b.getFirstToken();
|
|
315
|
+
if (name) {
|
|
316
|
+
ret.push({
|
|
317
|
+
name: name.getStr().replace("!", ""),
|
|
318
|
+
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
319
|
+
direction: _abap_file_information_1.MethodParameterDirection.Exporting,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
const changing = node.findFirstExpression(Expressions.MethodDefChanging);
|
|
325
|
+
if (changing) {
|
|
326
|
+
for (const param of changing.findAllExpressions(Expressions.MethodParam)) {
|
|
327
|
+
const name = (_c = param.findDirectExpression(Expressions.MethodParamName)) === null || _c === void 0 ? void 0 : _c.getFirstToken();
|
|
328
|
+
if (name) {
|
|
329
|
+
ret.push({
|
|
330
|
+
name: name.getStr().replace("!", ""),
|
|
331
|
+
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
332
|
+
direction: _abap_file_information_1.MethodParameterDirection.Changing,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const returning = node.findFirstExpression(Expressions.MethodDefReturning);
|
|
338
|
+
if (returning) {
|
|
339
|
+
const name = (_d = returning.findDirectExpression(Expressions.MethodParamName)) === null || _d === void 0 ? void 0 : _d.getFirstToken();
|
|
340
|
+
if (name) {
|
|
341
|
+
ret.push({
|
|
342
|
+
name: name.getStr().replace("!", ""),
|
|
343
|
+
identifier: new _identifier_1.Identifier(name, this.filename),
|
|
344
|
+
direction: _abap_file_information_1.MethodParameterDirection.Returning,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return ret;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
exports.ABAPFileInformationParser = ABAPFileInformationParser;
|
|
352
|
+
//# sourceMappingURL=abap_file_information_parser.js.map
|
|
@@ -17,7 +17,7 @@ const _syntax_input_1 = require("../_syntax_input");
|
|
|
17
17
|
const isSimple = /^\w+$/;
|
|
18
18
|
class Select {
|
|
19
19
|
static runSyntax(node, input, skipImplicitInto = false) {
|
|
20
|
-
var _a
|
|
20
|
+
var _a;
|
|
21
21
|
const token = node.getFirstToken();
|
|
22
22
|
let from = node.findDirectExpression(Expressions.SQLFrom);
|
|
23
23
|
if (from === undefined) {
|
|
@@ -38,10 +38,8 @@ class Select {
|
|
|
38
38
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
|
-
const isSingle = ((_a = node.getChildren()[1]) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase()) === "SINGLE"
|
|
42
|
-
|| node.get() instanceof Expressions.SelectLoop;
|
|
43
41
|
this.checkFields(fields, dbSources, input, node);
|
|
44
|
-
this.handleInto(node, input, fields, dbSources
|
|
42
|
+
const intoExpression = this.handleInto(node, input, fields, dbSources);
|
|
45
43
|
const fae = node.findDirectExpression(Expressions.SQLForAllEntries);
|
|
46
44
|
if (fae) {
|
|
47
45
|
input.scope.push(_scope_type_1.ScopeType.OpenSQL, "SELECT", token.getStart(), input.filename);
|
|
@@ -55,7 +53,7 @@ class Select {
|
|
|
55
53
|
&& node.findDirectExpression(Expressions.SQLIntoTable) === undefined
|
|
56
54
|
&& node.findDirectExpression(Expressions.SQLIntoList) === undefined
|
|
57
55
|
&& node.findDirectExpression(Expressions.SQLIntoStructure) === undefined) {
|
|
58
|
-
const fields = (
|
|
56
|
+
const fields = (_a = node.findFirstExpression(Expressions.SQLAggregation)) === null || _a === void 0 ? void 0 : _a.concatTokens();
|
|
59
57
|
const c = new RegExp(/^count\(\s*\*\s*\)$/, "i");
|
|
60
58
|
if (fields === undefined || c.test(fields) === false) {
|
|
61
59
|
const nameToken = from === null || from === void 0 ? void 0 : from.findDirectExpression(Expressions.SQLFromSource);
|
|
@@ -89,8 +87,18 @@ class Select {
|
|
|
89
87
|
for (const s of node.findAllExpressions(Expressions.SQLCompare)) {
|
|
90
88
|
sql_compare_1.SQLCompare.runSyntax(s, input, dbSources);
|
|
91
89
|
}
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
const orderBy = node.findDirectExpression(Expressions.SQLOrderBy);
|
|
91
|
+
if (orderBy) {
|
|
92
|
+
sql_order_by_1.SQLOrderBy.runSyntax(orderBy, input);
|
|
93
|
+
const where = node.findDirectExpression(Expressions.SQLCond);
|
|
94
|
+
if (intoExpression
|
|
95
|
+
&& where
|
|
96
|
+
&& intoExpression.getFirstToken().getStart().isBefore(orderBy.getFirstToken().getStart())
|
|
97
|
+
&& where.getFirstToken().getStart().isBefore(orderBy.getFirstToken().getStart())
|
|
98
|
+
&& where.getFirstToken().getStart().isBefore(intoExpression.getFirstToken().getStart())) {
|
|
99
|
+
const message = `ORDER BY must be before INTO, after WHERE`;
|
|
100
|
+
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, orderBy.getFirstToken(), message));
|
|
101
|
+
}
|
|
94
102
|
}
|
|
95
103
|
if (this.isStrictMode(node)) {
|
|
96
104
|
this.strictModeChecks(node, input);
|
|
@@ -141,13 +149,14 @@ class Select {
|
|
|
141
149
|
input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
|
|
142
150
|
}
|
|
143
151
|
}
|
|
144
|
-
static handleInto(node, input, fields, dbSources
|
|
152
|
+
static handleInto(node, input, fields, dbSources) {
|
|
145
153
|
const intoTable = node.findDirectExpression(Expressions.SQLIntoTable);
|
|
146
154
|
if (intoTable) {
|
|
147
155
|
const inline = intoTable.findFirstExpression(Expressions.InlineData);
|
|
148
156
|
if (inline) {
|
|
149
157
|
inline_data_1.InlineData.runSyntax(inline, input, this.buildTableType(fields, dbSources, input.scope));
|
|
150
158
|
}
|
|
159
|
+
return intoTable;
|
|
151
160
|
}
|
|
152
161
|
const intoStructure = node.findDirectExpression(Expressions.SQLIntoStructure);
|
|
153
162
|
if (intoStructure) {
|
|
@@ -161,6 +170,7 @@ class Select {
|
|
|
161
170
|
inline_data_1.InlineData.runSyntax(inline, input, basic_1.VoidType.get("SELECT_todo1"));
|
|
162
171
|
}
|
|
163
172
|
}
|
|
173
|
+
return intoStructure;
|
|
164
174
|
}
|
|
165
175
|
const intoList = node.findDirectExpression(Expressions.SQLIntoList);
|
|
166
176
|
if (intoList) {
|
|
@@ -200,7 +210,9 @@ class Select {
|
|
|
200
210
|
inline_data_1.InlineData.runSyntax(inline, input, type);
|
|
201
211
|
}
|
|
202
212
|
}
|
|
213
|
+
return intoList;
|
|
203
214
|
}
|
|
215
|
+
return undefined;
|
|
204
216
|
}
|
|
205
217
|
static checkFields(fields, dbSources, input, node) {
|
|
206
218
|
if (dbSources.length > 1) {
|
|
@@ -15,12 +15,12 @@ class ABAPFile extends _abstract_file_1.AbstractFile {
|
|
|
15
15
|
getRaw() {
|
|
16
16
|
return this.file.getRaw();
|
|
17
17
|
}
|
|
18
|
-
getInfo() {
|
|
19
|
-
return this.info;
|
|
20
|
-
}
|
|
21
18
|
getRawRows() {
|
|
22
19
|
return this.file.getRawRows();
|
|
23
20
|
}
|
|
21
|
+
getInfo() {
|
|
22
|
+
return this.info;
|
|
23
|
+
}
|
|
24
24
|
getStructure() {
|
|
25
25
|
return this.structure;
|
|
26
26
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ABAPParser = void 0;
|
|
4
|
-
const
|
|
4
|
+
const abap_file_1 = require("./abap_file");
|
|
5
|
+
const abap_file_information_1 = require("./4_file_information/abap_file_information");
|
|
6
|
+
const abap_file_information_parser_1 = require("./4_file_information/abap_file_information_parser");
|
|
5
7
|
const lexer_1 = require("./1_lexer/lexer");
|
|
6
8
|
const statement_parser_1 = require("./2_statements/statement_parser");
|
|
7
9
|
const structure_parser_1 = require("./3_structures/structure_parser");
|
|
8
|
-
const
|
|
9
|
-
const abap_file_1 = require("./abap_file");
|
|
10
|
+
const version_1 = require("../version");
|
|
10
11
|
class ABAPParser {
|
|
11
12
|
constructor(version, globalMacros, reg) {
|
|
12
13
|
this.version = version ? version : version_1.defaultVersion;
|
|
@@ -31,7 +32,9 @@ class ABAPParser {
|
|
|
31
32
|
for (const f of statementResult) {
|
|
32
33
|
const result = structure_parser_1.StructureParser.run(f);
|
|
33
34
|
// 4: file information
|
|
34
|
-
const
|
|
35
|
+
const parser = new abap_file_information_parser_1.ABAPFileInformationParser(f.file.getFilename());
|
|
36
|
+
const parsed = parser.parse(result.node);
|
|
37
|
+
const info = new abap_file_information_1.ABAPFileInformation(parsed);
|
|
35
38
|
output.push(new abap_file_1.ABAPFile(f.file, f.tokens, f.statements, result.node, info));
|
|
36
39
|
issues.push(...result.issues);
|
|
37
40
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EmailTemplate = void 0;
|
|
4
|
+
const _abstract_object_1 = require("./_abstract_object");
|
|
5
|
+
class EmailTemplate extends _abstract_object_1.AbstractObject {
|
|
6
|
+
getType() {
|
|
7
|
+
return "SMTG";
|
|
8
|
+
}
|
|
9
|
+
getAllowedNaming() {
|
|
10
|
+
return {
|
|
11
|
+
maxLength: 60, // todo
|
|
12
|
+
allowNamespace: true,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
getDescription() {
|
|
16
|
+
// todo
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.EmailTemplate = EmailTemplate;
|
|
21
|
+
//# sourceMappingURL=email_template.js.map
|
|
@@ -36,7 +36,6 @@ __exportStar(require("./behavior_definition"), exports);
|
|
|
36
36
|
__exportStar(require("./brf_plus_system_application"), exports);
|
|
37
37
|
__exportStar(require("./bsp_application"), exports);
|
|
38
38
|
__exportStar(require("./business_add_in_implementation"), exports);
|
|
39
|
-
__exportStar(require("./cds_entity_buffer"), exports);
|
|
40
39
|
__exportStar(require("./business_catalog_app_assignment"), exports);
|
|
41
40
|
__exportStar(require("./business_catalog"), exports);
|
|
42
41
|
__exportStar(require("./business_configuration_maintenance_object"), exports);
|
|
@@ -45,6 +44,7 @@ __exportStar(require("./business_function_assignment"), exports);
|
|
|
45
44
|
__exportStar(require("./business_function_set_assignment"), exports);
|
|
46
45
|
__exportStar(require("./business_object_model"), exports);
|
|
47
46
|
__exportStar(require("./business_object_type"), exports);
|
|
47
|
+
__exportStar(require("./cds_entity_buffer"), exports);
|
|
48
48
|
__exportStar(require("./cds_metadata_extension"), exports);
|
|
49
49
|
__exportStar(require("./cds_type"), exports);
|
|
50
50
|
__exportStar(require("./change_document"), exports);
|
|
@@ -70,6 +70,7 @@ __exportStar(require("./domain"), exports);
|
|
|
70
70
|
__exportStar(require("./ecatt_test_configuration"), exports);
|
|
71
71
|
__exportStar(require("./ecatt_test_data_container"), exports);
|
|
72
72
|
__exportStar(require("./ecatt_test_script"), exports);
|
|
73
|
+
__exportStar(require("./email_template"), exports);
|
|
73
74
|
__exportStar(require("./enhancement_implementation"), exports);
|
|
74
75
|
__exportStar(require("./enhancement_spot"), exports);
|
|
75
76
|
__exportStar(require("./entity_type"), exports);
|
|
@@ -40,6 +40,13 @@ class Table extends _abstract_object_1.AbstractObject {
|
|
|
40
40
|
}
|
|
41
41
|
return (_a = this.parsedData) === null || _a === void 0 ? void 0 : _a.description;
|
|
42
42
|
}
|
|
43
|
+
getSecondaryIndexes() {
|
|
44
|
+
var _a;
|
|
45
|
+
if (this.parsedData === undefined) {
|
|
46
|
+
this.parseXML();
|
|
47
|
+
}
|
|
48
|
+
return (_a = this.parsedData) === null || _a === void 0 ? void 0 : _a.secondaryIndexes;
|
|
49
|
+
}
|
|
43
50
|
getAllowedNaming() {
|
|
44
51
|
let length = 30;
|
|
45
52
|
const regex = /^((\/[A-Z_\d]{3,8}\/)|[a-zA-Z0-9]{3}|CI_)\w+$/;
|
|
@@ -267,7 +274,7 @@ class Table extends _abstract_object_1.AbstractObject {
|
|
|
267
274
|
}
|
|
268
275
|
///////////////
|
|
269
276
|
parseXML() {
|
|
270
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
277
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
271
278
|
const parsed = super.parseRaw2();
|
|
272
279
|
if (parsed === undefined) {
|
|
273
280
|
return;
|
|
@@ -306,6 +313,25 @@ class Table extends _abstract_object_1.AbstractObject {
|
|
|
306
313
|
DDTEXT: field.DDTEXT,
|
|
307
314
|
});
|
|
308
315
|
}
|
|
316
|
+
// secondary indexes
|
|
317
|
+
const indexes = (_m = parsed.abapGit["asx:abap"]["asx:values"]) === null || _m === void 0 ? void 0 : _m.DD12V;
|
|
318
|
+
;
|
|
319
|
+
this.parsedData.secondaryIndexes = [];
|
|
320
|
+
for (const index of (0, xml_utils_1.xmlToArray)(indexes === null || indexes === void 0 ? void 0 : indexes.DD12V)) {
|
|
321
|
+
const indexName = index.INDEXNAME;
|
|
322
|
+
const indexFields = [];
|
|
323
|
+
const indexFieldsXml = (_o = parsed.abapGit["asx:abap"]["asx:values"]) === null || _o === void 0 ? void 0 : _o.DD17V;
|
|
324
|
+
for (const indexField of (0, xml_utils_1.xmlToArray)(indexFieldsXml === null || indexFieldsXml === void 0 ? void 0 : indexFieldsXml.DD17V)) {
|
|
325
|
+
if (indexField.INDEXNAME === indexName) {
|
|
326
|
+
// assumption: fields are listed by POSITION in the xml
|
|
327
|
+
indexFields.push(indexField.FIELDNAME);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
this.parsedData.secondaryIndexes.push({
|
|
331
|
+
name: indexName,
|
|
332
|
+
fields: indexFields,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
309
335
|
}
|
|
310
336
|
}
|
|
311
337
|
exports.Table = Table;
|
package/build/src/registry.js
CHANGED
|
@@ -8,6 +8,10 @@ const _irule_1 = require("./_irule");
|
|
|
8
8
|
const objects_1 = require("../objects");
|
|
9
9
|
const severity_1 = require("../severity");
|
|
10
10
|
class CheckIncludeConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.allowUnused = false;
|
|
14
|
+
}
|
|
11
15
|
}
|
|
12
16
|
exports.CheckIncludeConf = CheckIncludeConf;
|
|
13
17
|
class CheckInclude {
|
|
@@ -35,7 +39,7 @@ class CheckInclude {
|
|
|
35
39
|
}
|
|
36
40
|
initialize(reg) {
|
|
37
41
|
this.reg = reg;
|
|
38
|
-
this.graph = new include_graph_1.IncludeGraph(this.reg, this.getConfig().severity || severity_1.Severity.Error);
|
|
42
|
+
this.graph = new include_graph_1.IncludeGraph(this.reg, this.getConfig().severity || severity_1.Severity.Error, this.getConfig().allowUnused || false);
|
|
39
43
|
return this;
|
|
40
44
|
}
|
|
41
45
|
run(obj) {
|
|
@@ -28,8 +28,7 @@ https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-us/abapstart-of-selectio
|
|
|
28
28
|
tags: [_irule_1.RuleTag.SingleFile],
|
|
29
29
|
badExample: `REPORT zfoo.
|
|
30
30
|
WRITE 'hello'.`,
|
|
31
|
-
goodExample: `
|
|
32
|
-
START-OF-SELECTION.
|
|
31
|
+
goodExample: `START-OF-SELECTION.
|
|
33
32
|
WRITE 'hello'.`,
|
|
34
33
|
};
|
|
35
34
|
}
|
package/build/src/rules/index.js
CHANGED
|
@@ -83,6 +83,7 @@ __exportStar(require("./implement_methods"), exports);
|
|
|
83
83
|
__exportStar(require("./implicit_start_of_selection"), exports);
|
|
84
84
|
__exportStar(require("./in_statement_indentation"), exports);
|
|
85
85
|
__exportStar(require("./indentation"), exports);
|
|
86
|
+
__exportStar(require("./index_completely_contained"), exports);
|
|
86
87
|
__exportStar(require("./inline_data_old_versions"), exports);
|
|
87
88
|
__exportStar(require("./intf_referencing_clas"), exports);
|
|
88
89
|
__exportStar(require("./invalid_table_index"), exports);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IndexCompletelyContained = exports.IndexCompletelyContainedConf = void 0;
|
|
4
|
+
const _basic_rule_config_1 = require("./_basic_rule_config");
|
|
5
|
+
const _irule_1 = require("./_irule");
|
|
6
|
+
const issue_1 = require("../issue");
|
|
7
|
+
const position_1 = require("../position");
|
|
8
|
+
const Objects = require("../objects");
|
|
9
|
+
class IndexCompletelyContainedConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
10
|
+
}
|
|
11
|
+
exports.IndexCompletelyContainedConf = IndexCompletelyContainedConf;
|
|
12
|
+
class IndexCompletelyContained {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.conf = new IndexCompletelyContainedConf();
|
|
15
|
+
}
|
|
16
|
+
getMetadata() {
|
|
17
|
+
return {
|
|
18
|
+
key: "index_completely_contained",
|
|
19
|
+
title: "Check if database table indexes are completely contained",
|
|
20
|
+
shortDescription: `If indexes are completely contained in other indexes, they can be removed to improve performance.`,
|
|
21
|
+
tags: [_irule_1.RuleTag.Performance, _irule_1.RuleTag.SingleFile],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
initialize() {
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
getConfig() {
|
|
28
|
+
return this.conf;
|
|
29
|
+
}
|
|
30
|
+
setConfig(conf) {
|
|
31
|
+
this.conf = conf;
|
|
32
|
+
}
|
|
33
|
+
run(obj) {
|
|
34
|
+
if (!(obj instanceof Objects.Table)) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
const indexes = obj.getSecondaryIndexes();
|
|
38
|
+
if (indexes === undefined || indexes.length === 0) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
const issues = [];
|
|
42
|
+
for (let i = 0; i < indexes.length; i++) {
|
|
43
|
+
const indexA = indexes[i];
|
|
44
|
+
for (let j = 0; j < indexes.length; j++) {
|
|
45
|
+
if (i === j) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const indexB = indexes[j];
|
|
49
|
+
let contained = true;
|
|
50
|
+
for (const field of indexA.fields) {
|
|
51
|
+
if (indexB.fields.indexOf(field) === -1) {
|
|
52
|
+
contained = false;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (contained) {
|
|
57
|
+
const position = new position_1.Position(1, 1);
|
|
58
|
+
const message = `Index "${indexA.name}" is completely contained in index "${indexB.name}"`;
|
|
59
|
+
issues.push(issue_1.Issue.atPosition(obj.getFiles()[0], position, message, this.getMetadata().key, this.conf.severity));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return issues;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.IndexCompletelyContained = IndexCompletelyContained;
|
|
67
|
+
//# sourceMappingURL=index_completely_contained.js.map
|
|
@@ -60,11 +60,12 @@ class Graph {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
class IncludeGraph {
|
|
63
|
-
constructor(reg, severity = severity_1.Severity.Error) {
|
|
63
|
+
constructor(reg, severity = severity_1.Severity.Error, allowUnused = false) {
|
|
64
64
|
this.reg = reg;
|
|
65
65
|
this.issues = [];
|
|
66
66
|
this.graph = new Graph();
|
|
67
67
|
this.severity = severity;
|
|
68
|
+
this.allowUnused = allowUnused;
|
|
68
69
|
this.build();
|
|
69
70
|
}
|
|
70
71
|
listMainForInclude(filename) {
|
|
@@ -88,6 +89,7 @@ class IncludeGraph {
|
|
|
88
89
|
}
|
|
89
90
|
const v = this.graph.findVertexByFilename(file.getFilename());
|
|
90
91
|
if (v !== undefined
|
|
92
|
+
&& this.allowUnused === false
|
|
91
93
|
&& v.include === true
|
|
92
94
|
&& this.listMainForInclude(v.filename).length === 0) {
|
|
93
95
|
const f = this.reg.getFileByName(v.filename);
|