@abaplint/core 2.115.1 → 2.115.3

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.
@@ -5493,12 +5493,20 @@ declare class ProvideFieldName extends Expression {
5493
5493
  }
5494
5494
 
5495
5495
  declare class ProxyObject extends AbstractObject {
5496
+ private parsedXML;
5496
5497
  getType(): string;
5497
5498
  getAllowedNaming(): {
5498
5499
  maxLength: number;
5499
5500
  allowNamespace: boolean;
5500
5501
  };
5501
5502
  getDescription(): string | undefined;
5503
+ setDirty(): void;
5504
+ parse(_version?: Version, _globalMacros?: readonly string[], reg?: IRegistry): {
5505
+ updated: boolean;
5506
+ runtime: number;
5507
+ };
5508
+ private parseXML;
5509
+ generateABAPObjects(): AbstractObject[];
5502
5510
  }
5503
5511
 
5504
5512
  declare class Public implements IStatement {
@@ -55,13 +55,18 @@ class InsertInternal {
55
55
  }
56
56
  }
57
57
  if (node.findDirectTokenByText("INITIAL") === undefined) {
58
- if (new _type_utils_1.TypeUtils(input.scope).isAssignableStrict(sourceType, targetType) === false) {
59
- const message = "Types not compatible";
60
- input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
61
- return;
58
+ let error = false;
59
+ if (sourceType instanceof basic_1.IntegerType && targetType instanceof basic_1.Integer8Type) {
60
+ error = true;
61
+ }
62
+ else if (new _type_utils_1.TypeUtils(input.scope).isAssignable(sourceType, targetType) === false) {
63
+ error = true;
62
64
  }
63
65
  else if (sourceType instanceof basic_1.CharacterType && targetType instanceof basic_1.StringType) {
64
66
  // yea, well, INSERT doesnt convert the values automatically, like everything else?
67
+ error = true;
68
+ }
69
+ if (error === true) {
65
70
  const message = "Types not compatible";
66
71
  input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
67
72
  return;
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ProxyObject = void 0;
4
+ const xml_utils_1 = require("../xml_utils");
4
5
  const _abstract_object_1 = require("./_abstract_object");
6
+ const interface_1 = require("./interface");
7
+ const memory_file_1 = require("../files/memory_file");
5
8
  class ProxyObject extends _abstract_object_1.AbstractObject {
6
9
  getType() {
7
10
  return "SPRX";
@@ -13,8 +16,83 @@ class ProxyObject extends _abstract_object_1.AbstractObject {
13
16
  };
14
17
  }
15
18
  getDescription() {
16
- // todo
17
- return undefined;
19
+ var _a;
20
+ this.parse();
21
+ const intfItem = (_a = this.parsedXML) === null || _a === void 0 ? void 0 : _a.proxyData.find(i => i.R3_TYPE === "INTF");
22
+ return intfItem === null || intfItem === void 0 ? void 0 : intfItem.R3_TEXT;
23
+ }
24
+ setDirty() {
25
+ this.parsedXML = undefined;
26
+ super.setDirty();
27
+ }
28
+ parse(_version, _globalMacros, reg) {
29
+ if (this.parsedXML) {
30
+ return { updated: false, runtime: 0 };
31
+ }
32
+ const start = Date.now();
33
+ this.parsedXML = this.parseXML();
34
+ const end = Date.now();
35
+ const objects = this.generateABAPObjects();
36
+ for (const obj of objects) {
37
+ reg === null || reg === void 0 ? void 0 : reg.addDependencies(obj.getFiles());
38
+ }
39
+ return { updated: true, runtime: end - start };
40
+ }
41
+ parseXML() {
42
+ var _a, _b;
43
+ const result = { proxyData: [] };
44
+ const parsed = super.parseRaw2();
45
+ if (parsed === undefined
46
+ || parsed.abapGit === undefined
47
+ || ((_a = parsed.abapGit["asx:abap"]) === null || _a === void 0 ? void 0 : _a["asx:values"]) === undefined) {
48
+ return result;
49
+ }
50
+ const values = parsed.abapGit["asx:abap"]["asx:values"];
51
+ result.proxyData = (0, xml_utils_1.xmlToArray)((_b = values.PROXY_DATA) === null || _b === void 0 ? void 0 : _b.item);
52
+ return result;
53
+ }
54
+ generateABAPObjects() {
55
+ var _a, _b, _c;
56
+ this.parse();
57
+ const result = [];
58
+ if (!this.parsedXML) {
59
+ return result;
60
+ }
61
+ // Find interface definition
62
+ const intfItem = this.parsedXML.proxyData.find(i => i.R3_TYPE === "INTF");
63
+ if (!intfItem || !intfItem.R3_NAME) {
64
+ return result;
65
+ }
66
+ const intfName = intfItem.R3_NAME.toLowerCase();
67
+ // Find methods
68
+ const methods = this.parsedXML.proxyData.filter(i => i.R3_TYPE === "METH");
69
+ // Build interface code
70
+ let code = `INTERFACE ${intfName} PUBLIC.\n`;
71
+ for (const method of methods) {
72
+ const methodName = (_a = method.R3_NAME) === null || _a === void 0 ? void 0 : _a.toLowerCase();
73
+ if (!methodName) {
74
+ continue;
75
+ }
76
+ // Find parameters for this method
77
+ const params = this.parsedXML.proxyData.filter(i => i.R3_TYPE === "PAIM" && i.OBJ_NAME1 === method.OBJ_NAME1);
78
+ code += ` METHODS ${methodName}\n`;
79
+ if (params.length > 0) {
80
+ code += ` IMPORTING\n`;
81
+ for (let i = 0; i < params.length; i++) {
82
+ const param = params[i];
83
+ const paramName = (_b = param.OBJ_NAME2) === null || _b === void 0 ? void 0 : _b.toLowerCase();
84
+ const paramType = (_c = param.OBJ_NAME_R) === null || _c === void 0 ? void 0 : _c.toLowerCase();
85
+ const isLast = i === params.length - 1;
86
+ code += ` ${paramName} TYPE ${paramType}${isLast ? "." : ""}\n`;
87
+ }
88
+ }
89
+ }
90
+ code += `ENDINTERFACE.`;
91
+ // Create the interface object
92
+ const intf = new interface_1.Interface(intfName.toUpperCase());
93
+ intf.addFile(new memory_file_1.MemoryFile(`${intfName}.intf.abap`, code));
94
+ result.push(intf);
95
+ return result;
18
96
  }
19
97
  }
20
98
  exports.ProxyObject = ProxyObject;
@@ -8,14 +8,39 @@ class RenameICFService {
8
8
  this.reg = reg;
9
9
  }
10
10
  buildEdits(obj, oldName, newName) {
11
+ var _a, _b, _c, _d;
11
12
  if (!(obj instanceof __1.ICFService)) {
12
13
  throw new Error("RenameICFService, not a ICF Service");
13
14
  }
15
+ // Preserve GUID suffix from the stored object/file name for the filename rename
16
+ // SICF files follow pattern: servicename.sicf or servicename {GUID}.sicf
17
+ const fileNewName = (() => {
18
+ // Look for pattern: space + GUID (32 hex chars in braces) + optional extension
19
+ const guidPattern = / \{[0-9A-Fa-f]{16,32}\}/;
20
+ const match = oldName.match(guidPattern);
21
+ if (match) {
22
+ // Extract everything from the GUID onwards (includes .sicf extension if present)
23
+ const guidIndex = match.index;
24
+ const suffix = oldName.substring(guidIndex);
25
+ // Only append suffix if newName doesn't already contain it
26
+ return newName.includes(suffix) ? newName : newName + suffix;
27
+ }
28
+ // Fallback: preserve any suffix after first space (legacy behavior)
29
+ const space = oldName.indexOf(" ");
30
+ if (space > -1) {
31
+ const suffix = oldName.substring(space);
32
+ return newName.includes(suffix) ? newName : newName + suffix;
33
+ }
34
+ return newName;
35
+ })();
36
+ const cleanOldName = (_b = (_a = oldName.match(/^[^ ]+/)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : oldName;
37
+ const cleanNewName = (_d = (_c = newName.match(/^[^ ]+/)) === null || _c === void 0 ? void 0 : _c[0]) !== null && _d !== void 0 ? _d : newName;
14
38
  let changes = [];
15
39
  const helper = new renamer_helper_1.RenamerHelper(this.reg);
16
- changes = changes.concat(helper.buildXMLFileEdits(obj, "ICF_NAME", oldName, newName));
17
- changes = changes.concat(helper.buildXMLFileEdits(obj, "ORIG_NAME", oldName, newName));
18
- changes = changes.concat(helper.renameFiles(obj, oldName, newName));
40
+ changes = changes.concat(helper.buildURLFileEdits(obj, cleanOldName, cleanNewName));
41
+ changes = changes.concat(helper.buildXMLFileEdits(obj, "ICF_NAME", cleanOldName, cleanNewName));
42
+ changes = changes.concat(helper.buildXMLFileEdits(obj, "ORIG_NAME", cleanOldName, cleanNewName, true));
43
+ changes = changes.concat(helper.renameFiles(obj, oldName, fileNewName));
19
44
  return {
20
45
  documentChanges: changes,
21
46
  };
@@ -32,7 +32,10 @@ class Renamer {
32
32
  /** Builds edits, but does not apply to registry, used by LSP */
33
33
  buildEdits(type, oldName, newName) {
34
34
  this.reg.parse(); // the registry must be parsed to dermine references
35
- const obj = this.reg.getObject(type, oldName);
35
+ let obj = this.reg.getObject(type, oldName);
36
+ if (obj === undefined && type === "SICF") {
37
+ obj = Array.from(this.reg.getObjects()).find(o => o.getType() === "SICF" && o.getName().toUpperCase().startsWith(oldName.toUpperCase() + " "));
38
+ }
36
39
  if (obj === undefined) {
37
40
  throw new Error("rename, object not found");
38
41
  }
@@ -102,21 +102,51 @@ class RenamerHelper {
102
102
  }
103
103
  return changes;
104
104
  }
105
- buildXMLFileEdits(object, xmlTag, oldName, newName) {
105
+ buildXMLFileEdits(object, xmlTag, oldName, newName, useLowerCase = false) {
106
106
  const changes = [];
107
107
  const xml = object.getXMLFile();
108
108
  if (xml === undefined) {
109
109
  return [];
110
110
  }
111
+ const originalValue = useLowerCase ? oldName.toLowerCase() : oldName.toUpperCase();
112
+ const replacementValue = useLowerCase ? newName.toLowerCase() : newName.toUpperCase();
111
113
  const tag = xmlTag.toUpperCase();
112
- const search = "<" + tag + ">" + oldName.toUpperCase() + "</" + tag + ">";
114
+ const search = "<" + tag + ">" + originalValue + "</" + tag + ">";
113
115
  const length = tag.length + 2;
114
116
  const rows = xml.getRawRows();
115
117
  for (let i = 0; i < rows.length; i++) {
116
118
  const index = rows[i].indexOf(search);
117
119
  if (index >= 0) {
118
- const range = vscode_languageserver_types_1.Range.create(i, index + length, i, index + oldName.length + length);
119
- changes.push(vscode_languageserver_types_1.TextDocumentEdit.create({ uri: xml.getFilename(), version: 1 }, [vscode_languageserver_types_1.TextEdit.replace(range, newName.toUpperCase())]));
120
+ const range = vscode_languageserver_types_1.Range.create(i, index + length, i, index + originalValue.length + length);
121
+ changes.push(vscode_languageserver_types_1.TextDocumentEdit.create({ uri: xml.getFilename(), version: 1 }, [vscode_languageserver_types_1.TextEdit.replace(range, replacementValue)]));
122
+ }
123
+ }
124
+ return changes;
125
+ }
126
+ buildURLFileEdits(object, oldName, newName) {
127
+ const changes = [];
128
+ const xml = object.getXMLFile();
129
+ if (xml === undefined) {
130
+ return [];
131
+ }
132
+ const oldNameLower = oldName.toLowerCase();
133
+ const newNameLower = newName.toLowerCase();
134
+ const rows = xml.getRawRows();
135
+ for (let i = 0; i < rows.length; i++) {
136
+ const row = rows[i];
137
+ const urlTagStart = row.indexOf("<URL>");
138
+ if (urlTagStart === -1) {
139
+ continue;
140
+ }
141
+ const urlTagEnd = row.indexOf("</URL>");
142
+ if (urlTagEnd === -1) {
143
+ continue;
144
+ }
145
+ const urlContent = row.substring(urlTagStart + 5, urlTagEnd);
146
+ const updatedUrl = urlContent.replace(oldNameLower, newNameLower);
147
+ if (updatedUrl !== urlContent) {
148
+ const range = vscode_languageserver_types_1.Range.create(i, urlTagStart + 5, i, urlTagEnd);
149
+ changes.push(vscode_languageserver_types_1.TextDocumentEdit.create({ uri: xml.getFilename(), version: 1 }, [vscode_languageserver_types_1.TextEdit.replace(range, updatedUrl)]));
120
150
  }
121
151
  }
122
152
  return changes;
@@ -74,7 +74,7 @@ class Registry {
74
74
  }
75
75
  static abaplintVersion() {
76
76
  // magic, see build script "version.sh"
77
- return "2.115.1";
77
+ return "2.115.3";
78
78
  }
79
79
  getDDICReferences() {
80
80
  return this.ddicReferences;
@@ -42,7 +42,8 @@ lv_value = 5.`,
42
42
  const source = (_a = statement.findDirectExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase();
43
43
  const target = (_b = statement.findDirectExpression(Expressions.Target)) === null || _b === void 0 ? void 0 : _b.concatTokens().toUpperCase();
44
44
  if (source === target && source !== undefined) {
45
- issues.push(issue_1.Issue.atStatement(file, statement, "Comment between methods in global class implementation", this.getMetadata().key, this.conf.severity));
45
+ const message = `Identical MOVE from "${source}" to "${target}"`;
46
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
46
47
  }
47
48
  }
48
49
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.115.1",
3
+ "version": "2.115.3",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -55,7 +55,7 @@
55
55
  "@types/mocha": "^10.0.10",
56
56
  "@types/node": "^24.10.3",
57
57
  "chai": "^4.5.0",
58
- "eslint": "^9.39.1",
58
+ "eslint": "^9.39.2",
59
59
  "mocha": "^11.7.5",
60
60
  "c8": "^10.1.3",
61
61
  "source-map-support": "^0.5.21",