@abaplint/core 2.108.13 → 2.109.0

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.
@@ -3132,6 +3132,11 @@ export declare interface IFile {
3132
3132
  getRawRows(): string[];
3133
3133
  }
3134
3134
 
3135
+ declare interface IFilenameAndToken {
3136
+ filename: string;
3137
+ token: Token;
3138
+ }
3139
+
3135
3140
  declare interface IFormDefinition extends Identifier {
3136
3141
  getTablesParameters(): readonly TypedIdentifier[];
3137
3142
  getUsingParameters(): readonly TypedIdentifier[];
@@ -3211,6 +3216,14 @@ declare interface ILookupResult {
3211
3216
  object?: IObject;
3212
3217
  }
3213
3218
 
3219
+ declare interface IMacroReferences {
3220
+ addDefinition(ref: IFilenameAndToken): void;
3221
+ addReference(ref: IFilenameAndToken): void;
3222
+ listDefinitionsByFile(filename: string): IFilenameAndToken[];
3223
+ listUsagesbyMacro(filename: string, token: Token): IFilenameAndToken[];
3224
+ clear(filename: string): void;
3225
+ }
3226
+
3214
3227
  declare interface IMatch {
3215
3228
  matched: StatementNode[];
3216
3229
  unmatched: StatementNode[];
@@ -3651,6 +3664,7 @@ export declare interface IRegistry {
3651
3664
  inErrorNamespace(name: string): boolean;
3652
3665
  getDDICReferences(): IDDICReferences;
3653
3666
  getMSAGReferences(): IMSAGReferences;
3667
+ getMacroReferences(): IMacroReferences;
3654
3668
  getConfig(): IConfiguration;
3655
3669
  setConfig(conf: IConfiguration): IRegistry;
3656
3670
  /** Get all objects, including dependencies */
@@ -5246,11 +5260,13 @@ export declare class Registry implements IRegistry {
5246
5260
  private readonly dependencies;
5247
5261
  private readonly ddicReferences;
5248
5262
  private readonly msagReferences;
5263
+ private readonly macroReferences;
5249
5264
  private conf;
5250
5265
  constructor(conf?: IConfiguration);
5251
5266
  static abaplintVersion(): string;
5252
5267
  getDDICReferences(): IDDICReferences;
5253
5268
  getMSAGReferences(): IMSAGReferences;
5269
+ getMacroReferences(): IMacroReferences;
5254
5270
  getObjects(): Generator<IObject, void, undefined>;
5255
5271
  getObjectsByType(type: string): Generator<IObject, void, undefined>;
5256
5272
  getFiles(): Generator<IFile, void, undefined>;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=_imacro_references.js.map
@@ -15,17 +15,23 @@ class Macros {
15
15
  constructor(globalMacros) {
16
16
  this.macros = {};
17
17
  for (const m of globalMacros) {
18
- this.macros[m.toUpperCase()] = [];
18
+ this.macros[m.toUpperCase()] = {
19
+ statements: [],
20
+ filename: undefined,
21
+ };
19
22
  }
20
23
  }
21
- addMacro(name, contents) {
24
+ addMacro(name, contents, filename) {
22
25
  if (this.isMacro(name)) {
23
26
  return;
24
27
  }
25
- this.macros[name.toUpperCase()] = contents;
28
+ this.macros[name.toUpperCase()] = {
29
+ statements: contents,
30
+ filename: filename,
31
+ };
26
32
  }
27
33
  getContents(name) {
28
- return this.macros[name.toUpperCase()];
34
+ return this.macros[name.toUpperCase()].statements;
29
35
  }
30
36
  listMacroNames() {
31
37
  return Object.keys(this.macros);
@@ -36,6 +42,9 @@ class Macros {
36
42
  }
37
43
  return false;
38
44
  }
45
+ getMacroFilename(name) {
46
+ return this.macros[name.toUpperCase()].filename;
47
+ }
39
48
  }
40
49
  class ExpandMacros {
41
50
  // "reg" must be supplied if there are cross object macros via INCLUDE
@@ -45,35 +54,38 @@ class ExpandMacros {
45
54
  this.globalMacros = globalMacros;
46
55
  this.reg = reg;
47
56
  }
48
- find(statements) {
49
- var _a, _b;
50
- let name = undefined;
57
+ find(statements, file) {
58
+ var _a, _b, _c;
59
+ let nameToken = undefined;
51
60
  let contents = [];
61
+ const macroReferences = (_a = this.reg) === null || _a === void 0 ? void 0 : _a.getMacroReferences();
62
+ macroReferences === null || macroReferences === void 0 ? void 0 : macroReferences.clear(file.getFilename());
52
63
  for (let i = 0; i < statements.length; i++) {
53
64
  const statement = statements[i];
54
65
  const type = statement.get();
55
66
  if (type instanceof Statements.Define) {
56
67
  // todo, will this break if first token is a pragma?
57
- name = statement.getTokens()[1].getStr();
68
+ nameToken = statement.getTokens()[1];
58
69
  contents = [];
59
70
  }
60
71
  else if (type instanceof Statements.Include) {
61
- const includeName = (_a = statement.findDirectExpression(Expressions.IncludeName)) === null || _a === void 0 ? void 0 : _a.concatTokens();
72
+ const includeName = (_b = statement.findDirectExpression(Expressions.IncludeName)) === null || _b === void 0 ? void 0 : _b.concatTokens();
62
73
  // todo, this does not take function module includes into account
63
- const prog = (_b = this.reg) === null || _b === void 0 ? void 0 : _b.getObject("PROG", includeName);
74
+ const prog = (_c = this.reg) === null || _c === void 0 ? void 0 : _c.getObject("PROG", includeName);
64
75
  if (prog) {
65
76
  prog.parse(this.version, this.globalMacros, this.reg);
66
- const main = prog.getMainABAPFile();
67
- if (main) {
77
+ const includeMainFile = prog.getMainABAPFile();
78
+ if (includeMainFile) {
68
79
  // slow, this copies everything,
69
- this.find([...main.getStatements()]);
80
+ this.find([...includeMainFile.getStatements()], includeMainFile);
70
81
  }
71
82
  }
72
83
  }
73
- else if (name) {
84
+ else if (nameToken) {
74
85
  if (type instanceof Statements.EndOfDefinition) {
75
- this.macros.addMacro(name, contents);
76
- name = undefined;
86
+ this.macros.addMacro(nameToken.getStr(), contents, file.getFilename());
87
+ macroReferences === null || macroReferences === void 0 ? void 0 : macroReferences.addDefinition({ filename: file.getFilename(), token: nameToken });
88
+ nameToken = undefined;
77
89
  }
78
90
  else if (!(type instanceof _statement_1.Comment)) {
79
91
  statements[i] = new statement_node_1.StatementNode(new _statement_1.MacroContent()).setChildren(this.tokensToNodes(statement.getTokens()));
@@ -82,17 +94,26 @@ class ExpandMacros {
82
94
  }
83
95
  }
84
96
  }
85
- handleMacros(statements) {
97
+ handleMacros(statements, file) {
98
+ var _a;
86
99
  const result = [];
87
100
  let containsUnknown = false;
101
+ const macroReferences = (_a = this.reg) === null || _a === void 0 ? void 0 : _a.getMacroReferences();
88
102
  for (const statement of statements) {
89
103
  const type = statement.get();
90
104
  if (type instanceof _statement_1.Unknown || type instanceof _statement_1.MacroCall) {
91
105
  const macroName = this.findName(statement.getTokens());
92
106
  if (macroName && this.macros.isMacro(macroName)) {
107
+ const filename = this.macros.getMacroFilename(macroName);
108
+ if (filename) {
109
+ macroReferences === null || macroReferences === void 0 ? void 0 : macroReferences.addReference({
110
+ filename: filename,
111
+ token: statement.getFirstToken(),
112
+ });
113
+ }
93
114
  result.push(new statement_node_1.StatementNode(new _statement_1.MacroCall(), statement.getColon()).setChildren(this.tokensToNodes(statement.getTokens())));
94
115
  const expanded = this.expandContents(macroName, statement);
95
- const handled = this.handleMacros(expanded);
116
+ const handled = this.handleMacros(expanded, file);
96
117
  for (const e of handled.statements) {
97
118
  result.push(e);
98
119
  }
@@ -82,10 +82,10 @@ class StatementParser {
82
82
  for (const w of wa) {
83
83
  this.process(w);
84
84
  this.categorize(w);
85
- macros.find(w.statements);
85
+ macros.find(w.statements, w.file);
86
86
  }
87
87
  for (const w of wa) {
88
- const res = macros.handleMacros(w.statements);
88
+ const res = macros.handleMacros(w.statements, w.file);
89
89
  w.statements = res.statements;
90
90
  if (res.containsUnknown === true) {
91
91
  this.lazyUnknown(w);
@@ -61,6 +61,9 @@ class CodeActions {
61
61
  const diagnostics = [];
62
62
  const fixes = [];
63
63
  for (const i of issues) {
64
+ if (i.getKey() !== key) {
65
+ continue;
66
+ }
64
67
  const fix = i.getDefaultFix();
65
68
  if (fix === undefined) {
66
69
  continue;
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Hover = void 0;
4
+ const Tokens = require("../abap/1_lexer/tokens");
5
+ const Statements = require("../abap/2_statements/statements");
4
6
  const LServer = require("vscode-languageserver-types");
5
7
  const _abap_object_1 = require("../objects/_abap_object");
6
8
  const _lsp_utils_1 = require("./_lsp_utils");
7
- const Tokens = require("../abap/1_lexer/tokens");
8
9
  const _lookup_1 = require("./_lookup");
9
10
  class Hover {
10
11
  constructor(reg) {
@@ -29,6 +30,9 @@ class Hover {
29
30
  || found.token instanceof Tokens.StringTemplateMiddle) {
30
31
  return { kind: LServer.MarkupKind.Markdown, value: "String Template" };
31
32
  }
33
+ else if (found.snode.get() instanceof Statements.Define && found.stack.length === 2) {
34
+ return { kind: LServer.MarkupKind.Markdown, value: "Macro Name" };
35
+ }
32
36
  else if (found.token instanceof Tokens.Comment) {
33
37
  let type = "Comment";
34
38
  if (found.token.getStr().startsWith(`"!`)) {
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MacroReferences = void 0;
4
+ class MacroReferences {
5
+ constructor() {
6
+ this.definitions = {};
7
+ this.references = {};
8
+ }
9
+ addDefinition(ref) {
10
+ if (this.definitions[ref.filename] === undefined) {
11
+ this.definitions[ref.filename] = [];
12
+ }
13
+ this.definitions[ref.filename].push(ref);
14
+ }
15
+ addReference(ref) {
16
+ if (this.references[ref.filename] === undefined) {
17
+ this.references[ref.filename] = [];
18
+ }
19
+ this.references[ref.filename].push(ref);
20
+ }
21
+ listDefinitionsByFile(filename) {
22
+ return this.definitions[filename] || [];
23
+ }
24
+ listUsagesbyMacro(filename, token) {
25
+ const ret = [];
26
+ const tokenStr = token.getStr().toUpperCase();
27
+ for (const ref of this.references[filename] || []) {
28
+ if (ref.token.getStr().toUpperCase() === tokenStr) {
29
+ ret.push(ref);
30
+ }
31
+ }
32
+ return ret;
33
+ }
34
+ clear(filename) {
35
+ delete this.definitions[filename];
36
+ delete this.references[filename];
37
+ }
38
+ }
39
+ exports.MacroReferences = MacroReferences;
40
+ //# sourceMappingURL=macro_references.js.map
@@ -8,6 +8,7 @@ const excludeHelper_1 = require("./utils/excludeHelper");
8
8
  const ddic_references_1 = require("./ddic_references");
9
9
  const rules_runner_1 = require("./rules_runner");
10
10
  const msag_references_1 = require("./msag_references");
11
+ const macro_references_1 = require("./macro_references");
11
12
  // todo, this should really be an instance in case there are multiple Registry'ies
12
13
  class ParsingPerformance {
13
14
  static clear() {
@@ -62,10 +63,11 @@ class Registry {
62
63
  this.conf = conf ? conf : config_1.Config.getDefault();
63
64
  this.ddicReferences = new ddic_references_1.DDICReferences();
64
65
  this.msagReferences = new msag_references_1.MSAGReferences();
66
+ this.macroReferences = new macro_references_1.MacroReferences();
65
67
  }
66
68
  static abaplintVersion() {
67
69
  // magic, see build script "version.sh"
68
- return "2.108.13";
70
+ return "2.109.0";
69
71
  }
70
72
  getDDICReferences() {
71
73
  return this.ddicReferences;
@@ -73,6 +75,9 @@ class Registry {
73
75
  getMSAGReferences() {
74
76
  return this.msagReferences;
75
77
  }
78
+ getMacroReferences() {
79
+ return this.macroReferences;
80
+ }
76
81
  *getObjects() {
77
82
  for (const name in this.objects) {
78
83
  for (const type in this.objects[name]) {
@@ -31,6 +31,7 @@ __exportStar(require("./cds_legacy_view"), exports);
31
31
  __exportStar(require("./cds_parser_error"), exports);
32
32
  __exportStar(require("./chain_mainly_declarations"), exports);
33
33
  __exportStar(require("./change_if_to_case"), exports);
34
+ __exportStar(require("./unused_macros"), exports);
34
35
  __exportStar(require("./check_abstract"), exports);
35
36
  __exportStar(require("./check_comments"), exports);
36
37
  __exportStar(require("./check_ddic"), exports);
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UnusedMacros = exports.UnusedMacrosConf = void 0;
4
+ const issue_1 = require("../issue");
5
+ const _basic_rule_config_1 = require("./_basic_rule_config");
6
+ const _irule_1 = require("./_irule");
7
+ const _abap_object_1 = require("../objects/_abap_object");
8
+ class UnusedMacrosConf extends _basic_rule_config_1.BasicRuleConfig {
9
+ constructor() {
10
+ super(...arguments);
11
+ /** skip specific names, case insensitive
12
+ * @uniqueItems true
13
+ */
14
+ this.skipNames = [];
15
+ }
16
+ }
17
+ exports.UnusedMacrosConf = UnusedMacrosConf;
18
+ class UnusedMacros {
19
+ constructor() {
20
+ this.conf = new UnusedMacrosConf();
21
+ }
22
+ getMetadata() {
23
+ return {
24
+ key: "unused_macros",
25
+ title: "Unused macros",
26
+ shortDescription: `Checks for unused macro definitions definitions`,
27
+ tags: [_irule_1.RuleTag.Quickfix],
28
+ };
29
+ }
30
+ getConfig() {
31
+ return this.conf;
32
+ }
33
+ setConfig(conf) {
34
+ this.conf = conf;
35
+ if (this.conf.skipNames === undefined) {
36
+ this.conf.skipNames = [];
37
+ }
38
+ }
39
+ initialize(reg) {
40
+ this.reg = reg;
41
+ return this;
42
+ }
43
+ run(obj) {
44
+ var _a;
45
+ const result = [];
46
+ if (!(obj instanceof _abap_object_1.ABAPObject)) {
47
+ return [];
48
+ }
49
+ const references = this.reg.getMacroReferences();
50
+ for (const file of obj.getABAPFiles()) {
51
+ for (const macro of references.listDefinitionsByFile(file.getFilename())) {
52
+ const usages = references.listUsagesbyMacro(file.getFilename(), macro.token);
53
+ if (usages.length === 0 && ((_a = this.conf.skipNames) === null || _a === void 0 ? void 0 : _a.includes(macro.token.getStr().toUpperCase())) === false) {
54
+ const message = "Unused macro definition: " + macro.token.getStr();
55
+ result.push(issue_1.Issue.atToken(file, macro.token, message, this.getMetadata().key, this.conf.severity));
56
+ }
57
+ }
58
+ }
59
+ return result;
60
+ }
61
+ }
62
+ exports.UnusedMacros = UnusedMacros;
63
+ //# sourceMappingURL=unused_macros.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.108.13",
3
+ "version": "2.109.0",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -50,10 +50,10 @@
50
50
  },
51
51
  "homepage": "https://abaplint.org",
52
52
  "devDependencies": {
53
- "@microsoft/api-extractor": "^7.46.2",
53
+ "@microsoft/api-extractor": "^7.47.0",
54
54
  "@types/chai": "^4.3.16",
55
55
  "@types/mocha": "^10.0.6",
56
- "@types/node": "^20.14.0",
56
+ "@types/node": "^20.14.2",
57
57
  "chai": "^4.4.1",
58
58
  "eslint": "^8.57.0",
59
59
  "mocha": "^10.4.0",