abapgit-agent 1.14.3 → 1.14.4
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/package.json +1 -1
- package/src/commands/lint.js +58 -19
package/package.json
CHANGED
package/src/commands/lint.js
CHANGED
|
@@ -66,29 +66,44 @@ module.exports = {
|
|
|
66
66
|
const allFiles = [...new Set([...abapFiles, ...depFiles])];
|
|
67
67
|
cfg.global.files = allFiles.map(f => `/${f}`);
|
|
68
68
|
|
|
69
|
-
// Exclude dependency files from reporting — they are included only for
|
|
70
|
-
// cross-reference resolution. Only the originally changed files are reported on.
|
|
71
|
-
const abapFilesSet = new Set(abapFiles);
|
|
72
|
-
const excludedDeps = depFiles
|
|
73
|
-
.filter(f => !abapFilesSet.has(f))
|
|
74
|
-
.map(f => `/${f}`);
|
|
75
|
-
if (excludedDeps.length > 0) {
|
|
76
|
-
cfg.global.exclude = [...new Set([...(cfg.global.exclude || []), ...excludedDeps])];
|
|
77
|
-
}
|
|
78
|
-
|
|
79
69
|
const scopedConfig = '.abaplint-local.json';
|
|
80
70
|
fs.writeFileSync(scopedConfig, JSON.stringify(cfg, null, 2));
|
|
81
71
|
|
|
82
72
|
// ── Run abaplint ──────────────────────────────────────────────────────────
|
|
73
|
+
// Dep files are included in the scoped config so abaplint can resolve
|
|
74
|
+
// cross-references (e.g. implement_methods needs the interface source).
|
|
75
|
+
// When producing checkstyle output (CI mode), post-filter the XML to only
|
|
76
|
+
// keep <file> blocks for the originally changed files — suppressing any
|
|
77
|
+
// pre-existing issues in dependency files that were not part of this change.
|
|
83
78
|
try {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
{
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
79
|
+
if (outformat === 'checkstyle') {
|
|
80
|
+
// Run to a temp file, filter, then write to the final destination.
|
|
81
|
+
const tempOut = '.abaplint-raw.xml';
|
|
82
|
+
const abapFilesSet = new Set(abapFiles.map(f => path.resolve(f)));
|
|
83
|
+
try {
|
|
84
|
+
const result = spawnSync(
|
|
85
|
+
`npx @abaplint/cli@latest ${scopedConfig} --outformat checkstyle --outfile ${tempOut}`,
|
|
86
|
+
{ stdio: 'pipe', shell: true }
|
|
87
|
+
);
|
|
88
|
+
const raw = fs.existsSync(tempOut) ? fs.readFileSync(tempOut, 'utf8') : '<checkstyle version="8.0"/>';
|
|
89
|
+
const filtered = filterCheckstyleToFiles(raw, abapFilesSet);
|
|
90
|
+
if (outfile) {
|
|
91
|
+
fs.writeFileSync(outfile, filtered);
|
|
92
|
+
} else {
|
|
93
|
+
process.stdout.write(filtered);
|
|
94
|
+
}
|
|
95
|
+
const issueCount = (filtered.match(/<error /g) || []).length;
|
|
96
|
+
if (issueCount > 0) process.exitCode = 1;
|
|
97
|
+
} finally {
|
|
98
|
+
if (fs.existsSync(tempOut)) fs.unlinkSync(tempOut);
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
// Interactive: inherit stdio so abaplint's human-readable output flows through.
|
|
102
|
+
const result = spawnSync(
|
|
103
|
+
`npx @abaplint/cli@latest ${scopedConfig}`,
|
|
104
|
+
{ stdio: 'inherit', shell: true }
|
|
105
|
+
);
|
|
106
|
+
if (result.status !== 0) process.exitCode = result.status;
|
|
92
107
|
}
|
|
93
108
|
} finally {
|
|
94
109
|
fs.unlinkSync(scopedConfig);
|
|
@@ -178,7 +193,7 @@ function resolveDependencies(abapFiles, fileIndex) {
|
|
|
178
193
|
|
|
179
194
|
// Patterns to extract referenced object names from ABAP source
|
|
180
195
|
const patterns = [
|
|
181
|
-
/^\s*INTERFACES
|
|
196
|
+
/^\s*INTERFACES:?\s+(\w+)\s*\./gim,
|
|
182
197
|
/INHERITING\s+FROM\s+(\w+)/gim,
|
|
183
198
|
/TYPE\s+REF\s+TO\s+(\w+)/gim,
|
|
184
199
|
];
|
|
@@ -238,6 +253,30 @@ function resolveDependencies(abapFiles, fileIndex) {
|
|
|
238
253
|
return [...deps];
|
|
239
254
|
}
|
|
240
255
|
|
|
256
|
+
/**
|
|
257
|
+
* Filter a checkstyle XML string to only include <file> blocks whose name
|
|
258
|
+
* attribute resolves to one of the files in the given Set of absolute paths.
|
|
259
|
+
* The outer <checkstyle> wrapper is preserved; the version attribute is kept.
|
|
260
|
+
*/
|
|
261
|
+
function filterCheckstyleToFiles(xml, abapFilesSet) {
|
|
262
|
+
// Extract the opening <checkstyle ...> tag (preserves version= attribute).
|
|
263
|
+
const headerMatch = xml.match(/^[\s\S]*?(<checkstyle[^>]*>)/);
|
|
264
|
+
const header = headerMatch ? headerMatch[1] : '<checkstyle version="8.0">';
|
|
265
|
+
|
|
266
|
+
// Match each <file name="...">...</file> block (including self-closing).
|
|
267
|
+
const fileBlockRe = /<file\s+name="([^"]*)"[\s\S]*?<\/file>|<file\s+name="([^"]*)"\s*\/>/g;
|
|
268
|
+
const kept = [];
|
|
269
|
+
let match;
|
|
270
|
+
while ((match = fileBlockRe.exec(xml)) !== null) {
|
|
271
|
+
const filePath = match[1] || match[2];
|
|
272
|
+
if (abapFilesSet.has(path.resolve(filePath))) {
|
|
273
|
+
kept.push(match[0]);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return `<?xml version="1.0" encoding="UTF-8"?>\n${header}\n${kept.join('\n')}${kept.length ? '\n' : ''}</checkstyle>\n`;
|
|
278
|
+
}
|
|
279
|
+
|
|
241
280
|
/**
|
|
242
281
|
* Keep only files that look like ABAP source files
|
|
243
282
|
* (name.type.abap or name.type.subtype.abap).
|