@abaplint/core 2.94.24 → 2.95.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.
- package/build/abaplint.d.ts +0 -1
- package/build/src/abap/2_statements/expressions/method_source.js +11 -6
- package/build/src/abap/5_syntax/expressions/field_chain.js +4 -17
- package/build/src/abap/5_syntax/expressions/method_source.js +110 -41
- package/build/src/abap/5_syntax/expressions/source_field.js +26 -0
- package/build/src/position.js +2 -3
- package/build/src/registry.js +1 -1
- package/build/src/rules/expand_macros.js +68 -0
- package/build/src/rules/index.js +1 -0
- package/package.json +1 -1
package/build/abaplint.d.ts
CHANGED
|
@@ -6398,7 +6398,6 @@ declare class VirtualEndPoint extends AbstractObject {
|
|
|
6398
6398
|
|
|
6399
6399
|
/** used for macro calls */
|
|
6400
6400
|
export declare class VirtualPosition extends Position {
|
|
6401
|
-
private readonly virtual;
|
|
6402
6401
|
readonly vrow: number;
|
|
6403
6402
|
readonly vcol: number;
|
|
6404
6403
|
constructor(virtual: Position, row: number, col: number);
|
|
@@ -6,12 +6,17 @@ const tokens_1 = require("../../1_lexer/tokens");
|
|
|
6
6
|
const _1 = require(".");
|
|
7
7
|
class MethodSource extends combi_1.Expression {
|
|
8
8
|
getRunnable() {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
|
|
9
|
+
// note: AttributeName can be both an attribute and a method name, the syntax check will tell
|
|
10
|
+
// note: its allowed to end with MethodCall, however if this is done it will give a syntax error via syntax check
|
|
11
|
+
const afterArrow = (0, combi_1.alt)(_1.AttributeName, _1.MethodCall, _1.Dynamic);
|
|
12
|
+
const arrow = (0, combi_1.altPrio)((0, combi_1.tok)(tokens_1.InstanceArrow), (0, combi_1.tok)(tokens_1.StaticArrow));
|
|
13
|
+
const attr = (0, combi_1.seq)(arrow, afterArrow);
|
|
14
|
+
const comp = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.Dash), _1.ComponentName);
|
|
15
|
+
const attrOrComp = (0, combi_1.altPrio)(attr, comp);
|
|
16
|
+
const staticClass = (0, combi_1.seq)(_1.ClassName, (0, combi_1.tok)(tokens_1.StaticArrow));
|
|
17
|
+
const clas = (0, combi_1.seq)(staticClass, afterArrow);
|
|
18
|
+
const start = (0, combi_1.seq)((0, combi_1.altPrio)(clas, _1.SourceField, _1.SourceFieldSymbol, _1.Dynamic), (0, combi_1.star)(attrOrComp));
|
|
19
|
+
return start;
|
|
15
20
|
}
|
|
16
21
|
}
|
|
17
22
|
exports.MethodSource = MethodSource;
|
|
@@ -14,6 +14,7 @@ const table_expression_1 = require("./table_expression");
|
|
|
14
14
|
const expressions_1 = require("../../2_statements/expressions");
|
|
15
15
|
const dereference_1 = require("./dereference");
|
|
16
16
|
const source_field_symbol_1 = require("./source_field_symbol");
|
|
17
|
+
const source_field_1 = require("./source_field");
|
|
17
18
|
class FieldChain {
|
|
18
19
|
runSyntax(node, scope, filename, refType) {
|
|
19
20
|
const concat = node.concatTokens();
|
|
@@ -110,23 +111,9 @@ class FieldChain {
|
|
|
110
111
|
&& node.get() instanceof Expressions.SourceFieldSymbol) {
|
|
111
112
|
return new source_field_symbol_1.SourceFieldSymbol().runSyntax(node, scope, filename);
|
|
112
113
|
}
|
|
113
|
-
else if (node
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const found = scope.findVariable(name);
|
|
117
|
-
if (found === undefined) {
|
|
118
|
-
throw new Error("\"" + name + "\" not found, findTop");
|
|
119
|
-
}
|
|
120
|
-
if (type) {
|
|
121
|
-
scope.addReference(token, found, type, filename);
|
|
122
|
-
}
|
|
123
|
-
if (name.includes("~")) {
|
|
124
|
-
const idef = scope.findInterfaceDefinition(name.split("~")[0]);
|
|
125
|
-
if (idef) {
|
|
126
|
-
scope.addReference(token, idef, _reference_1.ReferenceType.ObjectOrientedReference, filename);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return found.getType();
|
|
114
|
+
else if (node instanceof nodes_1.ExpressionNode
|
|
115
|
+
&& node.get() instanceof Expressions.SourceField) {
|
|
116
|
+
return new source_field_1.SourceField().runSyntax(node, scope, filename, type);
|
|
130
117
|
}
|
|
131
118
|
else if (node.get() instanceof Expressions.ClassName) {
|
|
132
119
|
const classTok = node.getFirstToken();
|
|
@@ -4,68 +4,137 @@ exports.MethodSource = void 0;
|
|
|
4
4
|
const Expressions = require("../../2_statements/expressions");
|
|
5
5
|
const nodes_1 = require("../../nodes");
|
|
6
6
|
const dynamic_1 = require("./dynamic");
|
|
7
|
-
const method_call_chain_1 = require("./method_call_chain");
|
|
8
7
|
const basic_1 = require("../../types/basic");
|
|
9
|
-
const types_1 = require("../../types");
|
|
10
8
|
const _reference_1 = require("../_reference");
|
|
11
9
|
const _object_oriented_1 = require("../_object_oriented");
|
|
10
|
+
const _abstract_type_1 = require("../../types/basic/_abstract_type");
|
|
11
|
+
const source_field_symbol_1 = require("./source_field_symbol");
|
|
12
|
+
const source_field_1 = require("./source_field");
|
|
13
|
+
const tokens_1 = require("../../1_lexer/tokens");
|
|
14
|
+
const attribute_name_1 = require("./attribute_name");
|
|
15
|
+
const component_name_1 = require("./component_name");
|
|
16
|
+
const types_1 = require("../../types");
|
|
12
17
|
class MethodSource {
|
|
13
18
|
runSyntax(node, scope, filename) {
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const first =
|
|
18
|
-
if (first
|
|
19
|
-
new
|
|
19
|
+
var _a;
|
|
20
|
+
const helper = new _object_oriented_1.ObjectOriented(scope);
|
|
21
|
+
const children = node.getChildren().slice();
|
|
22
|
+
const first = children.shift();
|
|
23
|
+
if (first === undefined) {
|
|
24
|
+
throw new Error("MethodSource, first child expected");
|
|
20
25
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
let context = this.findTop(first, scope, filename);
|
|
27
|
+
if (context === undefined) {
|
|
28
|
+
context = (_a = scope.findVariable("me")) === null || _a === void 0 ? void 0 : _a.getType();
|
|
29
|
+
children.unshift(first);
|
|
30
|
+
}
|
|
31
|
+
if (context instanceof basic_1.VoidType) {
|
|
32
|
+
// todo, if there are more dynamic with variables, the references for the variables are not added?
|
|
33
|
+
return context;
|
|
34
|
+
}
|
|
35
|
+
while (children.length > 0) {
|
|
36
|
+
const current = children.shift();
|
|
37
|
+
if (current === undefined) {
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
if (current.get() instanceof tokens_1.Dash) {
|
|
41
|
+
if (context instanceof basic_1.UnknownType) {
|
|
42
|
+
throw new Error("Not a structure, type unknown, MethodSource");
|
|
26
43
|
}
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
44
|
+
else if (!(context instanceof basic_1.StructureType)) {
|
|
45
|
+
throw new Error("Not a structure, MethodSource");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else if (current.get() instanceof tokens_1.InstanceArrow
|
|
49
|
+
|| current.get() instanceof tokens_1.StaticArrow) {
|
|
50
|
+
// todo, handling static vs instance
|
|
51
|
+
}
|
|
52
|
+
else if (current.get() instanceof Expressions.AttributeName
|
|
53
|
+
|| current.get() instanceof Expressions.SourceField) {
|
|
54
|
+
try {
|
|
55
|
+
if (context instanceof _abstract_type_1.AbstractType) {
|
|
56
|
+
const attr = new attribute_name_1.AttributeName().runSyntax(context, current, scope, filename, _reference_1.ReferenceType.DataReadReference);
|
|
57
|
+
context = attr;
|
|
58
|
+
continue;
|
|
37
59
|
}
|
|
60
|
+
}
|
|
61
|
+
catch (_b) {
|
|
62
|
+
// ignore
|
|
63
|
+
}
|
|
64
|
+
// try looking for method name
|
|
65
|
+
const className = context instanceof basic_1.ObjectReferenceType ? context.getIdentifierName() : undefined;
|
|
66
|
+
const methodToken = current.getFirstToken();
|
|
67
|
+
const methodName = methodToken === null || methodToken === void 0 ? void 0 : methodToken.getStr();
|
|
68
|
+
const def = scope.findObjectDefinition(className);
|
|
69
|
+
// eslint-disable-next-line prefer-const
|
|
70
|
+
let { method, def: foundDef } = helper.searchMethodName(def, methodName);
|
|
71
|
+
if (method === undefined && (methodName === null || methodName === void 0 ? void 0 : methodName.toUpperCase()) === "CONSTRUCTOR") {
|
|
72
|
+
context = new basic_1.VoidType("CONSTRUCTOR"); // todo, this is a workaround, constructors always exists
|
|
73
|
+
}
|
|
74
|
+
else if (method === undefined && !(context instanceof basic_1.VoidType)) {
|
|
75
|
+
throw new Error("Method or attribute \"" + methodName + "\" not found, MethodSource");
|
|
76
|
+
}
|
|
77
|
+
else if (method) {
|
|
38
78
|
const extra = {
|
|
39
79
|
ooName: foundDef === null || foundDef === void 0 ? void 0 : foundDef.getName(),
|
|
40
80
|
ooType: foundDef instanceof types_1.ClassDefinition ? "CLAS" : "INTF"
|
|
41
81
|
};
|
|
42
|
-
scope.addReference(
|
|
43
|
-
|
|
82
|
+
scope.addReference(methodToken, method, _reference_1.ReferenceType.MethodReference, filename, extra);
|
|
83
|
+
context = method;
|
|
44
84
|
}
|
|
45
85
|
}
|
|
46
|
-
else if (context instanceof
|
|
47
|
-
|
|
86
|
+
else if (current.get() instanceof Expressions.ComponentName && context instanceof _abstract_type_1.AbstractType) {
|
|
87
|
+
if (context instanceof basic_1.TableType && context.isWithHeader()) {
|
|
88
|
+
context = context.getRowType();
|
|
89
|
+
}
|
|
90
|
+
context = new component_name_1.ComponentName().runSyntax(context, current);
|
|
48
91
|
}
|
|
49
|
-
else {
|
|
50
|
-
|
|
92
|
+
else if (current instanceof nodes_1.ExpressionNode && current.get() instanceof Expressions.Dynamic) {
|
|
93
|
+
new dynamic_1.Dynamic().runSyntax(current, scope, filename);
|
|
94
|
+
context = new basic_1.VoidType("Dynamic");
|
|
51
95
|
}
|
|
52
96
|
}
|
|
53
|
-
|
|
54
|
-
new
|
|
97
|
+
if (context instanceof _abstract_type_1.AbstractType && !(context instanceof basic_1.VoidType)) {
|
|
98
|
+
throw new Error("Not a method, MethodSource");
|
|
55
99
|
}
|
|
56
|
-
else {
|
|
57
|
-
throw new Error("
|
|
100
|
+
else if (context === undefined) {
|
|
101
|
+
throw new Error("Not found, MethodSource");
|
|
58
102
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
103
|
+
return context;
|
|
104
|
+
}
|
|
105
|
+
//////////////////////////////////////
|
|
106
|
+
findTop(first, scope, filename) {
|
|
107
|
+
if (first.get() instanceof Expressions.ClassName) {
|
|
108
|
+
// todo, refactor this part to new expression handler,
|
|
109
|
+
const token = first.getFirstToken();
|
|
110
|
+
const className = token.getStr();
|
|
111
|
+
const classDefinition = scope.findObjectDefinition(className);
|
|
112
|
+
if (classDefinition === undefined && scope.getDDIC().inErrorNamespace(className) === false) {
|
|
113
|
+
const extra = { ooName: className, ooType: "Void" };
|
|
114
|
+
scope.addReference(token, undefined, _reference_1.ReferenceType.ObjectOrientedVoidReference, filename, extra);
|
|
115
|
+
return new basic_1.VoidType(className);
|
|
116
|
+
}
|
|
117
|
+
else if (classDefinition === undefined) {
|
|
118
|
+
throw new Error("Class " + className + " not found");
|
|
119
|
+
}
|
|
120
|
+
scope.addReference(first.getFirstToken(), classDefinition, _reference_1.ReferenceType.ObjectOrientedReference, filename);
|
|
121
|
+
return new basic_1.ObjectReferenceType(classDefinition);
|
|
63
122
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
123
|
+
else if (first instanceof nodes_1.ExpressionNode && first.get() instanceof Expressions.SourceField) {
|
|
124
|
+
try {
|
|
125
|
+
return new source_field_1.SourceField().runSyntax(first, scope, filename, _reference_1.ReferenceType.DataReadReference);
|
|
126
|
+
}
|
|
127
|
+
catch (_a) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else if (first instanceof nodes_1.ExpressionNode && first.get() instanceof Expressions.SourceFieldSymbol) {
|
|
132
|
+
return new source_field_symbol_1.SourceFieldSymbol().runSyntax(first, scope, filename);
|
|
133
|
+
}
|
|
134
|
+
else if (first instanceof nodes_1.ExpressionNode && first.get() instanceof Expressions.Dynamic) {
|
|
135
|
+
new dynamic_1.Dynamic().runSyntax(first, scope, filename);
|
|
136
|
+
return new basic_1.VoidType("Dynamic");
|
|
67
137
|
}
|
|
68
|
-
*/
|
|
69
138
|
return undefined;
|
|
70
139
|
}
|
|
71
140
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SourceField = void 0;
|
|
4
|
+
const _reference_1 = require("../_reference");
|
|
5
|
+
class SourceField {
|
|
6
|
+
runSyntax(node, scope, filename, type) {
|
|
7
|
+
const token = node.getFirstToken();
|
|
8
|
+
const name = token.getStr();
|
|
9
|
+
const found = scope.findVariable(name);
|
|
10
|
+
if (found === undefined) {
|
|
11
|
+
throw new Error("\"" + name + "\" not found, findTop");
|
|
12
|
+
}
|
|
13
|
+
if (type) {
|
|
14
|
+
scope.addReference(token, found, type, filename);
|
|
15
|
+
}
|
|
16
|
+
if (name.includes("~")) {
|
|
17
|
+
const idef = scope.findInterfaceDefinition(name.split("~")[0]);
|
|
18
|
+
if (idef) {
|
|
19
|
+
scope.addReference(token, idef, _reference_1.ReferenceType.ObjectOrientedReference, filename);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return found.getType();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.SourceField = SourceField;
|
|
26
|
+
//# sourceMappingURL=source_field.js.map
|
package/build/src/position.js
CHANGED
|
@@ -31,7 +31,7 @@ exports.Position = Position;
|
|
|
31
31
|
class VirtualPosition extends Position {
|
|
32
32
|
constructor(virtual, row, col) {
|
|
33
33
|
super(virtual.getRow(), virtual.getCol());
|
|
34
|
-
this.virtual = virtual;
|
|
34
|
+
// this.virtual = virtual;
|
|
35
35
|
this.vrow = row;
|
|
36
36
|
this.vcol = col;
|
|
37
37
|
}
|
|
@@ -39,8 +39,7 @@ class VirtualPosition extends Position {
|
|
|
39
39
|
if (!(p instanceof VirtualPosition)) {
|
|
40
40
|
return false;
|
|
41
41
|
}
|
|
42
|
-
|
|
43
|
-
return super.equals(this.virtual) && this.vrow === bar.vrow && this.vcol === bar.vcol;
|
|
42
|
+
return super.equals(this) && this.vrow === p.vrow && this.vcol === p.vcol;
|
|
44
43
|
}
|
|
45
44
|
}
|
|
46
45
|
exports.VirtualPosition = VirtualPosition;
|
package/build/src/registry.js
CHANGED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExpandMacros = exports.ExpandMacrosConf = void 0;
|
|
4
|
+
const issue_1 = require("../issue");
|
|
5
|
+
const _abap_rule_1 = require("./_abap_rule");
|
|
6
|
+
const _basic_rule_config_1 = require("./_basic_rule_config");
|
|
7
|
+
const _irule_1 = require("./_irule");
|
|
8
|
+
const edit_helper_1 = require("../edit_helper");
|
|
9
|
+
const _statement_1 = require("../abap/2_statements/statements/_statement");
|
|
10
|
+
const position_1 = require("../position");
|
|
11
|
+
class ExpandMacrosConf extends _basic_rule_config_1.BasicRuleConfig {
|
|
12
|
+
}
|
|
13
|
+
exports.ExpandMacrosConf = ExpandMacrosConf;
|
|
14
|
+
class ExpandMacros extends _abap_rule_1.ABAPRule {
|
|
15
|
+
constructor() {
|
|
16
|
+
super(...arguments);
|
|
17
|
+
this.conf = new ExpandMacrosConf();
|
|
18
|
+
}
|
|
19
|
+
getMetadata() {
|
|
20
|
+
return {
|
|
21
|
+
key: "expand_macros",
|
|
22
|
+
title: "Expand Macros",
|
|
23
|
+
shortDescription: `Allows expanding macro calls with quick fixes`,
|
|
24
|
+
extendedInformation: `Macros: https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abenmacros_guidl.htm
|
|
25
|
+
|
|
26
|
+
Note that macros/DEFINE cannot be used in the ABAP Cloud programming model`,
|
|
27
|
+
badExample: `DEFINE _hello.
|
|
28
|
+
WRITE 'hello'.
|
|
29
|
+
END-OF-DEFINITION.
|
|
30
|
+
_hello.`,
|
|
31
|
+
goodExample: `WRITE 'hello'.`,
|
|
32
|
+
tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.Upport],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
getConfig() {
|
|
36
|
+
return this.conf;
|
|
37
|
+
}
|
|
38
|
+
setConfig(conf) {
|
|
39
|
+
this.conf = conf;
|
|
40
|
+
}
|
|
41
|
+
runParsed(file) {
|
|
42
|
+
const issues = [];
|
|
43
|
+
const message = "Expand macro call";
|
|
44
|
+
const statements = file.getStatements();
|
|
45
|
+
for (let i = 0; i < statements.length; i++) {
|
|
46
|
+
const statementNode = statements[i];
|
|
47
|
+
const statement = statementNode.get();
|
|
48
|
+
if (!(statement instanceof _statement_1.MacroCall)) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
let replace = "";
|
|
52
|
+
for (let j = i + 1; j < statements.length; j++) {
|
|
53
|
+
const sub = statements[j];
|
|
54
|
+
if (sub.getFirstToken().getStart() instanceof position_1.VirtualPosition) {
|
|
55
|
+
replace += sub.concatTokens();
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const fix = edit_helper_1.EditHelper.replaceRange(file, statementNode.getStart(), statementNode.getEnd(), replace);
|
|
62
|
+
issues.push(issue_1.Issue.atStatement(file, statementNode, message, this.getMetadata().key, this.conf.severity, fix));
|
|
63
|
+
}
|
|
64
|
+
return issues;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.ExpandMacros = ExpandMacros;
|
|
68
|
+
//# sourceMappingURL=expand_macros.js.map
|
package/build/src/rules/index.js
CHANGED
|
@@ -57,6 +57,7 @@ __exportStar(require("./empty_line_in_statement"), exports);
|
|
|
57
57
|
__exportStar(require("./empty_statement"), exports);
|
|
58
58
|
__exportStar(require("./empty_structure"), exports);
|
|
59
59
|
__exportStar(require("./exit_or_check"), exports);
|
|
60
|
+
__exportStar(require("./expand_macros"), exports);
|
|
60
61
|
__exportStar(require("./exporting"), exports);
|
|
61
62
|
__exportStar(require("./forbidden_identifier"), exports);
|
|
62
63
|
__exportStar(require("./forbidden_pseudo_and_pragma"), exports);
|