@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.
@@ -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(structure, filename) {
13
- this.forms = [];
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
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=parsed_file_information.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, _b;
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, isSingle);
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 = (_b = node.findFirstExpression(Expressions.SQLAggregation)) === null || _b === void 0 ? void 0 : _b.concatTokens();
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
- for (const s of node.findDirectExpressions(Expressions.SQLOrderBy)) {
93
- sql_order_by_1.SQLOrderBy.runSyntax(s, input);
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, _isSingle) {
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 version_1 = require("../version");
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 abap_file_information_1 = require("./4_file_information/abap_file_information");
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 info = new abap_file_information_1.ABAPFileInformation(result.node, f.file.getFilename());
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,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=iabap_file.js.map
@@ -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
@@ -27,6 +27,8 @@ class FunctionGroup extends _abap_object_1.ABAPObject {
27
27
  super.setDirty();
28
28
  this.includes = undefined;
29
29
  this.modules = undefined;
30
+ this.description = undefined;
31
+ this.dynpros = undefined;
30
32
  }
31
33
  getAllowedNaming() {
32
34
  return {
@@ -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;
@@ -74,7 +74,7 @@ class Registry {
74
74
  }
75
75
  static abaplintVersion() {
76
76
  // magic, see build script "version.sh"
77
- return "2.113.247";
77
+ return "2.114.1";
78
78
  }
79
79
  getDDICReferences() {
80
80
  return this.ddicReferences;
@@ -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
  }
@@ -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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.113.247",
3
+ "version": "2.114.1",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",