arc-1 1.0.2 → 1.1.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/bin/arc1-cli.js +3 -7
- package/bin/arc1.js +4 -9
- package/dist/adt/abapgit.d.ts +10 -5
- package/dist/adt/abapgit.d.ts.map +1 -1
- package/dist/adt/abapgit.js +357 -76
- package/dist/adt/abapgit.js.map +1 -1
- package/dist/adt/atc.d.ts +49 -0
- package/dist/adt/atc.d.ts.map +1 -0
- package/dist/adt/atc.js +294 -0
- package/dist/adt/atc.js.map +1 -0
- package/dist/adt/aunit-package.d.ts +22 -0
- package/dist/adt/aunit-package.d.ts.map +1 -0
- package/dist/adt/aunit-package.js +78 -0
- package/dist/adt/aunit-package.js.map +1 -0
- package/dist/adt/aunit.d.ts +143 -0
- package/dist/adt/aunit.d.ts.map +1 -0
- package/dist/adt/aunit.js +987 -0
- package/dist/adt/aunit.js.map +1 -0
- package/dist/adt/client.d.ts +9 -7
- package/dist/adt/client.d.ts.map +1 -1
- package/dist/adt/client.js +55 -64
- package/dist/adt/client.js.map +1 -1
- package/dist/adt/config.d.ts +2 -0
- package/dist/adt/config.d.ts.map +1 -1
- package/dist/adt/config.js +1 -0
- package/dist/adt/config.js.map +1 -1
- package/dist/adt/devtools.d.ts +8 -30
- package/dist/adt/devtools.d.ts.map +1 -1
- package/dist/adt/devtools.js +41 -218
- package/dist/adt/devtools.js.map +1 -1
- package/dist/adt/diagnostics.d.ts +1 -1
- package/dist/adt/diagnostics.d.ts.map +1 -1
- package/dist/adt/diagnostics.js +12 -12
- package/dist/adt/diagnostics.js.map +1 -1
- package/dist/adt/errors.d.ts +7 -0
- package/dist/adt/errors.d.ts.map +1 -1
- package/dist/adt/errors.js +7 -0
- package/dist/adt/errors.js.map +1 -1
- package/dist/adt/features.d.ts +9 -3
- package/dist/adt/features.d.ts.map +1 -1
- package/dist/adt/features.js +40 -8
- package/dist/adt/features.js.map +1 -1
- package/dist/adt/gcts.d.ts +12 -45
- package/dist/adt/gcts.d.ts.map +1 -1
- package/dist/adt/gcts.js +299 -171
- package/dist/adt/gcts.js.map +1 -1
- package/dist/adt/http-deadline.d.ts +23 -0
- package/dist/adt/http-deadline.d.ts.map +1 -0
- package/dist/adt/http-deadline.js +106 -0
- package/dist/adt/http-deadline.js.map +1 -0
- package/dist/adt/http-wire-body.d.ts +2 -0
- package/dist/adt/http-wire-body.d.ts.map +1 -0
- package/dist/adt/http-wire-body.js +14 -0
- package/dist/adt/http-wire-body.js.map +1 -0
- package/dist/adt/http.d.ts +10 -24
- package/dist/adt/http.d.ts.map +1 -1
- package/dist/adt/http.js +89 -53
- package/dist/adt/http.js.map +1 -1
- package/dist/adt/path-safety.d.ts +16 -0
- package/dist/adt/path-safety.d.ts.map +1 -0
- package/dist/adt/path-safety.js +101 -0
- package/dist/adt/path-safety.js.map +1 -0
- package/dist/adt/semaphore.d.ts +2 -2
- package/dist/adt/semaphore.d.ts.map +1 -1
- package/dist/adt/semaphore.js +26 -9
- package/dist/adt/semaphore.js.map +1 -1
- package/dist/adt/source-diff.d.ts +10 -1
- package/dist/adt/source-diff.d.ts.map +1 -1
- package/dist/adt/source-diff.js +33 -7
- package/dist/adt/source-diff.js.map +1 -1
- package/dist/adt/text-search.d.ts +25 -0
- package/dist/adt/text-search.d.ts.map +1 -0
- package/dist/adt/text-search.js +152 -0
- package/dist/adt/text-search.js.map +1 -0
- package/dist/adt/transport-diff.d.ts +128 -0
- package/dist/adt/transport-diff.d.ts.map +1 -0
- package/dist/adt/transport-diff.js +524 -0
- package/dist/adt/transport-diff.js.map +1 -0
- package/dist/adt/transport.d.ts +78 -13
- package/dist/adt/transport.d.ts.map +1 -1
- package/dist/adt/transport.js +443 -41
- package/dist/adt/transport.js.map +1 -1
- package/dist/adt/types.d.ts +23 -12
- package/dist/adt/types.d.ts.map +1 -1
- package/dist/adt/xml-parser.d.ts +1 -8
- package/dist/adt/xml-parser.d.ts.map +1 -1
- package/dist/adt/xml-parser.js +54 -60
- package/dist/adt/xml-parser.js.map +1 -1
- package/dist/authz/policy.d.ts.map +1 -1
- package/dist/authz/policy.js +5 -2
- package/dist/authz/policy.js.map +1 -1
- package/dist/cli-args.d.ts +2 -2
- package/dist/cli-args.js +2 -2
- package/dist/cli-checks.d.ts +56 -0
- package/dist/cli-checks.d.ts.map +1 -0
- package/dist/cli-checks.js +368 -0
- package/dist/cli-checks.js.map +1 -0
- package/dist/cli.d.ts +68 -15
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +677 -297
- package/dist/cli.js.map +1 -1
- package/dist/handlers/cds-hints.d.ts.map +1 -1
- package/dist/handlers/cds-hints.js +1 -10
- package/dist/handlers/cds-hints.js.map +1 -1
- package/dist/handlers/diagnose.d.ts +4 -0
- package/dist/handlers/diagnose.d.ts.map +1 -1
- package/dist/handlers/diagnose.js +616 -9
- package/dist/handlers/diagnose.js.map +1 -1
- package/dist/handlers/dispatch.d.ts.map +1 -1
- package/dist/handlers/dispatch.js +40 -1
- package/dist/handlers/dispatch.js.map +1 -1
- package/dist/handlers/git.d.ts.map +1 -1
- package/dist/handlers/git.js +165 -84
- package/dist/handlers/git.js.map +1 -1
- package/dist/handlers/read.d.ts.map +1 -1
- package/dist/handlers/read.js +15 -0
- package/dist/handlers/read.js.map +1 -1
- package/dist/handlers/schemas.d.ts +15 -2
- package/dist/handlers/schemas.d.ts.map +1 -1
- package/dist/handlers/schemas.js +75 -6
- package/dist/handlers/schemas.js.map +1 -1
- package/dist/handlers/search.js +1 -1
- package/dist/handlers/search.js.map +1 -1
- package/dist/handlers/tools.d.ts.map +1 -1
- package/dist/handlers/tools.js +51 -42
- package/dist/handlers/tools.js.map +1 -1
- package/dist/handlers/transport.d.ts +2 -1
- package/dist/handlers/transport.d.ts.map +1 -1
- package/dist/handlers/transport.js +128 -27
- package/dist/handlers/transport.js.map +1 -1
- package/dist/handlers/write/create.d.ts.map +1 -1
- package/dist/handlers/write/create.js +11 -0
- package/dist/handlers/write/create.js.map +1 -1
- package/dist/handlers/write/update-delete.d.ts.map +1 -1
- package/dist/handlers/write/update-delete.js +33 -10
- package/dist/handlers/write/update-delete.js.map +1 -1
- package/dist/handlers/write-helpers.d.ts.map +1 -1
- package/dist/handlers/write-helpers.js +3 -2
- package/dist/handlers/write-helpers.js.map +1 -1
- package/dist/server/audit.d.ts +1 -1
- package/dist/server/audit.d.ts.map +1 -1
- package/dist/server/audit.js +228 -21
- package/dist/server/audit.js.map +1 -1
- package/dist/server/config.d.ts +16 -0
- package/dist/server/config.d.ts.map +1 -1
- package/dist/server/config.js +145 -17
- package/dist/server/config.js.map +1 -1
- package/dist/server/effective-policy-log.d.ts +2 -1
- package/dist/server/effective-policy-log.d.ts.map +1 -1
- package/dist/server/effective-policy-log.js +8 -2
- package/dist/server/effective-policy-log.js.map +1 -1
- package/dist/server/multi-target-runtime.d.ts.map +1 -1
- package/dist/server/multi-target-runtime.js +3 -0
- package/dist/server/multi-target-runtime.js.map +1 -1
- package/dist/server/multi-target-tools.d.ts.map +1 -1
- package/dist/server/multi-target-tools.js +5 -0
- package/dist/server/multi-target-tools.js.map +1 -1
- package/dist/server/server.d.ts +15 -13
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +36 -26
- package/dist/server/server.js.map +1 -1
- package/dist/server/types.d.ts +2 -0
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +1 -0
- package/dist/server/types.js.map +1 -1
- package/package.json +13 -13
package/dist/adt/config.d.ts
CHANGED
|
@@ -37,6 +37,8 @@ export interface AdtClientConfig {
|
|
|
37
37
|
language: string;
|
|
38
38
|
/** Skip TLS verification */
|
|
39
39
|
insecure: boolean;
|
|
40
|
+
/** Gzip non-empty data-preview POST bodies for approved WAF compatibility. */
|
|
41
|
+
gzipDataPreviewBody: boolean;
|
|
40
42
|
/** Cookie-based auth (alternative to basic auth) */
|
|
41
43
|
cookies: Record<string, string>;
|
|
42
44
|
/** Path to cookie file — enables hot-reload on stale auth */
|
package/dist/adt/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/adt/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,gEAAgE;AAChE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,IAAI,GAAG,KAAK,CAAC;AAEhD,0DAA0D;AAC1D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;IACrB,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,EAAE,WAAW,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,EAAE,WAAW,CAAC;IACjB,SAAS,EAAE,WAAW,CAAC;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB,GAAG,EAAE,WAAW,CAAC;CAClB;AAED,8CAA8C;AAC9C,wBAAgB,oBAAoB,IAAI,aAAa,CAYpD;AAED,+BAA+B;AAC/B,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2BAA2B;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,+BAA+B;IAC/B,QAAQ,EAAE,aAAa,CAAC;IACxB,6BAA6B;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,+EAA+E;IAC/E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,GAAG,CAAA;KAAE,KAAK,IAAI,CAAC;IACtE;;+EAE2E;IAC3E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;0FAEsF;IACtF,YAAY,CAAC,EAAE,OAAO,gBAAgB,EAAE,SAAS,CAAC;CACnD;AAED,uCAAuC;AACvC,wBAAgB,sBAAsB,IAAI,eAAe,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/adt/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,gEAAgE;AAChE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,IAAI,GAAG,KAAK,CAAC;AAEhD,0DAA0D;AAC1D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;IACrB,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,EAAE,WAAW,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,EAAE,WAAW,CAAC;IACjB,SAAS,EAAE,WAAW,CAAC;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB,GAAG,EAAE,WAAW,CAAC;CAClB;AAED,8CAA8C;AAC9C,wBAAgB,oBAAoB,IAAI,aAAa,CAYpD;AAED,+BAA+B;AAC/B,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,8EAA8E;IAC9E,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2BAA2B;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,+BAA+B;IAC/B,QAAQ,EAAE,aAAa,CAAC;IACxB,6BAA6B;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,+EAA+E;IAC/E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,GAAG,CAAA;KAAE,KAAK,IAAI,CAAC;IACtE;;+EAE2E;IAC3E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;0FAEsF;IACtF,YAAY,CAAC,EAAE,OAAO,gBAAgB,EAAE,SAAS,CAAC;CACnD;AAED,uCAAuC;AACvC,wBAAgB,sBAAsB,IAAI,eAAe,CAcxD"}
|
package/dist/adt/config.js
CHANGED
package/dist/adt/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/adt/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAkBvD,8CAA8C;AAC9C,MAAM,UAAU,oBAAoB;IAClC,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,MAAM;QACX,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,MAAM;QACX,SAAS,EAAE,MAAM;QACjB,OAAO,EAAE,MAAM;QACf,GAAG,EAAE,MAAM;KACZ,CAAC;AACJ,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/adt/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAkBvD,8CAA8C;AAC9C,MAAM,UAAU,oBAAoB;IAClC,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,MAAM;QACX,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,MAAM;QACX,SAAS,EAAE,MAAM;QACjB,OAAO,EAAE,MAAM;QACf,GAAG,EAAE,MAAM;KACZ,CAAC;AACJ,CAAC;AAoFD,uCAAuC;AACvC,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,EAAE;QACZ,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,KAAK;QACf,mBAAmB,EAAE,KAAK;QAC1B,OAAO,EAAE,EAAE;QACX,MAAM,EAAE,wBAAwB,EAAE;QAClC,QAAQ,EAAE,oBAAoB,EAAE;QAChC,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC"}
|
package/dist/adt/devtools.d.ts
CHANGED
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
* - RunUnitTests: execute ABAP unit tests
|
|
8
8
|
* - RunATCCheck: ABAP Test Cockpit (code quality)
|
|
9
9
|
*/
|
|
10
|
+
import { type AunitRunResult } from './aunit.js';
|
|
10
11
|
import type { AdtHttpClient } from './http.js';
|
|
12
|
+
import type { AdtRequestOptions } from './http-deadline.js';
|
|
11
13
|
import { type SafetyConfig } from './safety.js';
|
|
12
|
-
import type { CdsTestCasesResult, CoverageSummary, FixDelta, FixProposal, SyntaxCheckResult
|
|
13
|
-
|
|
14
|
+
import type { CdsTestCasesResult, CoverageSummary, FixDelta, FixProposal, SyntaxCheckResult } from './types.js';
|
|
15
|
+
export { type AtcFinding, type AtcRunResult, getAtcSystemDefaultVariant, listAtcVariants, runAtcCheck, } from './atc.js';
|
|
14
16
|
/** Run syntax check on an ABAP object.
|
|
15
17
|
*
|
|
16
18
|
* Two modes:
|
|
@@ -80,31 +82,16 @@ export interface PublishResult {
|
|
|
80
82
|
export declare function publishServiceBinding(http: AdtHttpClient, safety: SafetyConfig, name: string, version?: string, serviceType?: 'odatav2' | 'odatav4'): Promise<PublishResult>;
|
|
81
83
|
/** Unpublish an OData service binding (removes the service from consumption) */
|
|
82
84
|
export declare function unpublishServiceBinding(http: AdtHttpClient, safety: SafetyConfig, name: string, version?: string, serviceType?: 'odatav2' | 'odatav4'): Promise<PublishResult>;
|
|
83
|
-
/** Run ABAP unit tests for an object */
|
|
84
|
-
export declare function runUnitTests(http: AdtHttpClient, safety: SafetyConfig, objectUrl: string, opts?: {
|
|
85
|
+
/** Run ABAP unit tests for an object and return the canonical structured result. */
|
|
86
|
+
export declare function runUnitTests(http: AdtHttpClient, safety: SafetyConfig, objectUrl: string | string[], opts?: {
|
|
85
87
|
coverage?: boolean;
|
|
86
|
-
|
|
88
|
+
requestOptions?: AdtRequestOptions;
|
|
89
|
+
}): Promise<AunitRunResult>;
|
|
87
90
|
/** Extract the coverage-measurement URI from an abapunit testruns result run with coverage="true". */
|
|
88
91
|
export declare function extractCoverageMeasurementUri(testrunsXml: string): string | null;
|
|
89
92
|
/** Parse the object-level statement/branch/procedure aggregate from a coverage-measurement response,
|
|
90
93
|
* plus the per-method drill-down (methods below full statement coverage, worst-first). */
|
|
91
94
|
export declare function parseCoverageMeasurement(xml: string): CoverageSummary;
|
|
92
|
-
/**
|
|
93
|
-
* List the ATC check variants this system offers — the valid values for `runAtcCheck`'s `variant`.
|
|
94
|
-
* GETs the ADT named-item feed `/sap/bc/adt/atc/variants?name=<pattern>` (`*` = all). The `name`
|
|
95
|
-
* filter is a server-side prefix match, so an empty/omitted `name` returns an EMPTY list — always
|
|
96
|
-
* pass a pattern. Read-only. Live-verified on 758 (184 variants) + 816 (215).
|
|
97
|
-
*/
|
|
98
|
-
export declare function listAtcVariants(http: AdtHttpClient, safety: SafetyConfig, filter?: string): Promise<NamedItem[]>;
|
|
99
|
-
/**
|
|
100
|
-
* Read the system default ATC check variant from `/sap/bc/adt/atc/customizing` — the variant ATC
|
|
101
|
-
* uses when none is passed. Returns undefined if the endpoint/property is absent. Read-only.
|
|
102
|
-
*/
|
|
103
|
-
export declare function getAtcSystemDefaultVariant(http: AdtHttpClient, safety: SafetyConfig): Promise<string | undefined>;
|
|
104
|
-
/** Run ATC check on an object */
|
|
105
|
-
export declare function runAtcCheck(http: AdtHttpClient, safety: SafetyConfig, objectUrl: string, variant?: string): Promise<{
|
|
106
|
-
findings: AtcFinding[];
|
|
107
|
-
}>;
|
|
108
95
|
/**
|
|
109
96
|
* Get SAP-suggested ABAP Unit test cases for a CDS entity (CDS Test Double Framework).
|
|
110
97
|
*
|
|
@@ -130,15 +117,6 @@ export declare function supportsCdsTestCases(http: AdtHttpClient): boolean | und
|
|
|
130
117
|
export declare function getFixProposals(http: AdtHttpClient, safety: SafetyConfig, sourceUri: string, source: string, line: number, column: number): Promise<FixProposal[]>;
|
|
131
118
|
/** Apply one SAP quick fix proposal and return replacement deltas */
|
|
132
119
|
export declare function applyFixProposal(http: AdtHttpClient, safety: SafetyConfig, proposal: FixProposal, sourceUri: string, source: string, line: number, column: number): Promise<FixDelta[]>;
|
|
133
|
-
export interface AtcFinding {
|
|
134
|
-
priority: number;
|
|
135
|
-
checkTitle: string;
|
|
136
|
-
messageTitle: string;
|
|
137
|
-
uri: string;
|
|
138
|
-
line: number;
|
|
139
|
-
quickfixInfo?: string;
|
|
140
|
-
hasQuickfix?: boolean;
|
|
141
|
-
}
|
|
142
120
|
/** Discriminated outcome from parsing an activation response. */
|
|
143
121
|
export type ActivationOutcome = {
|
|
144
122
|
kind: 'success';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devtools.d.ts","sourceRoot":"","sources":["../../src/adt/devtools.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"devtools.d.ts","sourceRoot":"","sources":["../../src/adt/devtools.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,KAAK,cAAc,EAA0C,MAAM,YAAY,CAAC;AAEzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAiC,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAC/E,OAAO,KAAK,EAEV,kBAAkB,EAClB,eAAe,EAEf,QAAQ,EACR,WAAW,EAEX,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,0BAA0B,EAC1B,eAAe,EACf,WAAW,GACZ,MAAM,UAAU,CAAC;AAElB;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9D,OAAO,CAAC,iBAAiB,CAAC,CAkC5B;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,cAAc,GAAG,cAAc,GAAG,aAAa,GAAG,MAAM,CAAC;CACjE;AAED,oDAAoD;AACpD,wBAAsB,WAAW,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO5G;AAED,kDAAkD;AAClD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,qBAAqB,CAAC,CAqBhC;AAED,oDAAoD;AACpD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,qDAAqD;AACrD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wCAAwC;AACxC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED;;;;;8BAK8B;AAC9B,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9C,OAAO,CAAC,gBAAgB,CAAC,CA6B3B;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAC7C,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAC/B,OAAO,CAAC,gBAAgB,CAAC,CAwC3B;AA8LD,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAoFD,qFAAqF;AACrF,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,SAAS,EAChB,WAAW,GAAE,SAAS,GAAG,SAAqB,GAC7C,OAAO,CAAC,aAAa,CAAC,CAGxB;AAED,gFAAgF;AAChF,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,SAAS,EAChB,WAAW,GAAE,SAAS,GAAG,SAAqB,GAC7C,OAAO,CAAC,aAAa,CAAC,CAGxB;AAED,oFAAoF;AACpF,wBAAsB,YAAY,CAChC,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAC5B,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,iBAAiB,CAAA;CAAO,GACpE,OAAO,CAAC,cAAc,CAAC,CAkEzB;AAED,sGAAsG;AACtG,wBAAgB,6BAA6B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYhF;AA8DD;2FAC2F;AAC3F,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAarE;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,YAAY,EACpB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,kBAAkB,CAAC,CAQ7B;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,GAAG,SAAS,CAG7E;AAqBD,8DAA8D;AAC9D,wBAAsB,eAAe,CACnC,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,WAAW,EAAE,CAAC,CAkBxB;AAED,qEAAqE;AACrE,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,QAAQ,EAAE,CAAC,CA0BrB;AAID,iEAAiE;AACjE,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,iBAAiB,EAAE,CAAA;CAAE,GACrE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,iBAAiB,EAAE,CAAA;CAAE,GACnE;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B,CAAC;AAEN,8DAA8D;AAC9D,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAyDrE;AAED;4FAC4F;AAC5F,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAcnE"}
|
package/dist/adt/devtools.js
CHANGED
|
@@ -8,9 +8,12 @@
|
|
|
8
8
|
* - RunATCCheck: ABAP Test Cockpit (code quality)
|
|
9
9
|
*/
|
|
10
10
|
import { logger } from '../server/logger.js';
|
|
11
|
+
import { parseAunitRunResult, withAunitCoverage } from './aunit.js';
|
|
11
12
|
import { AdtApiError, AdtSafetyError } from './errors.js';
|
|
13
|
+
import { canonicalHostRelativeAdtPath } from './path-safety.js';
|
|
12
14
|
import { checkOperation, OperationType } from './safety.js';
|
|
13
|
-
import { decodeXmlEntities, escapeXmlAttr, findDeepNodes,
|
|
15
|
+
import { decodeXmlEntities, escapeXmlAttr, findDeepNodes, parseXml } from './xml-parser.js';
|
|
16
|
+
export { getAtcSystemDefaultVariant, listAtcVariants, runAtcCheck, } from './atc.js';
|
|
14
17
|
/** Run syntax check on an ABAP object.
|
|
15
18
|
*
|
|
16
19
|
* Two modes:
|
|
@@ -371,9 +374,15 @@ export async function unpublishServiceBinding(http, safety, name, version = '000
|
|
|
371
374
|
checkOperation(safety, OperationType.Activate, 'UnpublishServiceBinding');
|
|
372
375
|
return postPublishJob(http, serviceType, 'unpublishjob', name, version);
|
|
373
376
|
}
|
|
374
|
-
/** Run ABAP unit tests for an object */
|
|
377
|
+
/** Run ABAP unit tests for an object and return the canonical structured result. */
|
|
375
378
|
export async function runUnitTests(http, safety, objectUrl, opts = {}) {
|
|
376
379
|
checkOperation(safety, OperationType.Test, 'RunUnitTests');
|
|
380
|
+
const objectUrls = Array.isArray(objectUrl) ? objectUrl : [objectUrl];
|
|
381
|
+
if (objectUrls.length === 0)
|
|
382
|
+
throw new Error('ABAP Unit requires at least one object reference.');
|
|
383
|
+
const objectReferences = objectUrls
|
|
384
|
+
.map((url) => `<adtcore:objectReference adtcore:uri="${escapeXmlAttr(url)}"/>`)
|
|
385
|
+
.join('');
|
|
377
386
|
const body = `<?xml version="1.0" encoding="UTF-8"?>
|
|
378
387
|
<aunit:runConfiguration xmlns:aunit="http://www.sap.com/adt/aunit">
|
|
379
388
|
<external>
|
|
@@ -382,48 +391,58 @@ export async function runUnitTests(http, safety, objectUrl, opts = {}) {
|
|
|
382
391
|
<options>
|
|
383
392
|
<uriType value="semantic"/>
|
|
384
393
|
<testDeterminationStrategy sameProgram="true" assignedTests="false" publicApi="false"/>
|
|
385
|
-
<testRiskLevels harmless="true" dangerous="
|
|
394
|
+
<testRiskLevels harmless="true" dangerous="false" critical="false"/>
|
|
386
395
|
<testDurations short="true" medium="true" long="true"/>
|
|
387
396
|
</options>
|
|
388
397
|
<adtcore:objectSets xmlns:adtcore="http://www.sap.com/adt/core">
|
|
389
398
|
<objectSet kind="inclusive">
|
|
390
399
|
<adtcore:objectReferences>
|
|
391
|
-
|
|
400
|
+
${objectReferences}
|
|
392
401
|
</adtcore:objectReferences>
|
|
393
402
|
</objectSet>
|
|
394
403
|
</adtcore:objectSets>
|
|
395
404
|
</aunit:runConfiguration>`;
|
|
396
405
|
const resp = await http.post('/sap/bc/adt/abapunit/testruns', body, 'application/vnd.sap.adt.abapunit.testruns.config.v4+xml', {
|
|
397
406
|
Accept: 'application/vnd.sap.adt.abapunit.testruns.result.v2+xml',
|
|
398
|
-
});
|
|
399
|
-
const
|
|
407
|
+
}, opts.requestOptions);
|
|
408
|
+
const result = parseAunitRunResult(resp.body);
|
|
400
409
|
if (!opts.coverage)
|
|
401
|
-
return
|
|
410
|
+
return result;
|
|
402
411
|
// Coverage is a second step: the run result references a coverage measurement, which we POST
|
|
403
412
|
// (with the same object set) to retrieve the statement/branch/procedure aggregate. The endpoint is
|
|
404
413
|
// live-verified on 7.50 + 758 + 816 (2026-06-25); the best-effort fallback (missing URI / fetch
|
|
405
414
|
// failure / no valid metrics → return tests with no coverage) is defensive for unknown systems.
|
|
406
415
|
const measurementUri = extractCoverageMeasurementUri(resp.body);
|
|
407
|
-
if (!measurementUri)
|
|
408
|
-
return
|
|
416
|
+
if (!measurementUri) {
|
|
417
|
+
return withAunitCoverage(result, undefined, 'measurement_not_reported');
|
|
418
|
+
}
|
|
409
419
|
try {
|
|
410
420
|
const coverageQuery = `<?xml version="1.0" encoding="UTF-8"?>
|
|
411
|
-
<cov:query xmlns:cov="http://www.sap.com/adt/cov"><adtcore:objectSets xmlns:adtcore="http://www.sap.com/adt/core"><objectSet kind="inclusive"><adtcore:objectReferences
|
|
412
|
-
const measResp = await http.post(measurementUri, coverageQuery, 'application/xml', { Accept: 'application/xml' });
|
|
421
|
+
<cov:query xmlns:cov="http://www.sap.com/adt/cov"><adtcore:objectSets xmlns:adtcore="http://www.sap.com/adt/core"><objectSet kind="inclusive"><adtcore:objectReferences>${objectReferences}</adtcore:objectReferences></objectSet></adtcore:objectSets></cov:query>`;
|
|
422
|
+
const measResp = await http.post(measurementUri, coverageQuery, 'application/xml', { Accept: 'application/xml' }, opts.requestOptions);
|
|
413
423
|
const coverage = parseCoverageMeasurement(measResp.body);
|
|
414
|
-
return hasCoverageMetrics(coverage)
|
|
424
|
+
return hasCoverageMetrics(coverage)
|
|
425
|
+
? withAunitCoverage(result, coverage)
|
|
426
|
+
: withAunitCoverage(result, undefined, 'no_valid_metrics');
|
|
415
427
|
}
|
|
416
428
|
catch {
|
|
417
|
-
return
|
|
429
|
+
return withAunitCoverage(result, undefined, 'request_failed');
|
|
418
430
|
}
|
|
419
431
|
}
|
|
420
432
|
/** Extract the coverage-measurement URI from an abapunit testruns result run with coverage="true". */
|
|
421
433
|
export function extractCoverageMeasurementUri(testrunsXml) {
|
|
422
434
|
const parsed = parseXml(testrunsXml);
|
|
435
|
+
const measurementPrefix = '/sap/bc/adt/runtime/traces/coverage/measurements/';
|
|
423
436
|
for (const node of findDeepNodes(parsed, 'coverage')) {
|
|
424
437
|
const uri = node['@_uri'];
|
|
425
|
-
if (typeof uri
|
|
426
|
-
|
|
438
|
+
if (typeof uri !== 'string')
|
|
439
|
+
continue;
|
|
440
|
+
const canonical = canonicalHostRelativeAdtPath(uri, measurementPrefix);
|
|
441
|
+
if (!canonical || canonical.includes('?'))
|
|
442
|
+
continue;
|
|
443
|
+
const measurementId = canonical.slice(measurementPrefix.length);
|
|
444
|
+
if (/^[A-Za-z0-9_-]+$/.test(measurementId))
|
|
445
|
+
return canonical;
|
|
427
446
|
}
|
|
428
447
|
return null;
|
|
429
448
|
}
|
|
@@ -503,69 +522,6 @@ export function parseCoverageMeasurement(xml) {
|
|
|
503
522
|
function hasCoverageMetrics(summary) {
|
|
504
523
|
return Boolean(summary.statement || summary.branch || summary.procedure);
|
|
505
524
|
}
|
|
506
|
-
/**
|
|
507
|
-
* List the ATC check variants this system offers — the valid values for `runAtcCheck`'s `variant`.
|
|
508
|
-
* GETs the ADT named-item feed `/sap/bc/adt/atc/variants?name=<pattern>` (`*` = all). The `name`
|
|
509
|
-
* filter is a server-side prefix match, so an empty/omitted `name` returns an EMPTY list — always
|
|
510
|
-
* pass a pattern. Read-only. Live-verified on 758 (184 variants) + 816 (215).
|
|
511
|
-
*/
|
|
512
|
-
export async function listAtcVariants(http, safety, filter = '*') {
|
|
513
|
-
checkOperation(safety, OperationType.Read, 'ListAtcVariants');
|
|
514
|
-
const pattern = filter.trim() || '*';
|
|
515
|
-
const resp = await http.get(`/sap/bc/adt/atc/variants?name=${encodeURIComponent(pattern)}`, {
|
|
516
|
-
Accept: 'application/vnd.sap.adt.nameditems.v1+xml',
|
|
517
|
-
});
|
|
518
|
-
return parseNamedItems(resp.body).filter((item) => item.name);
|
|
519
|
-
}
|
|
520
|
-
/**
|
|
521
|
-
* Read the system default ATC check variant from `/sap/bc/adt/atc/customizing` — the variant ATC
|
|
522
|
-
* uses when none is passed. Returns undefined if the endpoint/property is absent. Read-only.
|
|
523
|
-
*/
|
|
524
|
-
export async function getAtcSystemDefaultVariant(http, safety) {
|
|
525
|
-
checkOperation(safety, OperationType.Read, 'GetAtcCustomizing');
|
|
526
|
-
const resp = await http.get('/sap/bc/adt/atc/customizing', { Accept: 'application/xml' });
|
|
527
|
-
return parseAtcSystemCheckVariant(resp.body);
|
|
528
|
-
}
|
|
529
|
-
/** Run ATC check on an object */
|
|
530
|
-
export async function runAtcCheck(http, safety, objectUrl, variant) {
|
|
531
|
-
checkOperation(safety, OperationType.Read, 'RunATCCheck');
|
|
532
|
-
// ATC is a three-step flow. The checks that actually run are selected by the *check
|
|
533
|
-
// variant bound to a worklist* — not by the run request. The previous implementation
|
|
534
|
-
// skipped worklist creation and POSTed straight to `/runs?worklistId=1`, so ATC executed
|
|
535
|
-
// no checks and always returned zero findings (and the `variant` argument was silently
|
|
536
|
-
// ignored — it only toggled `maximumVerdicts`). Verified live on A4H (S/4HANA 2023):
|
|
537
|
-
// a variant-bound worklist yields findings; the bare `worklistId=1` path does not.
|
|
538
|
-
// Step 1 — create a worklist bound to the check variant. Omitting `checkVariant` uses the
|
|
539
|
-
// system's configured default check variant (live-verified to produce findings). The
|
|
540
|
-
// response body is the plain-text worklist id.
|
|
541
|
-
const worklistPath = variant
|
|
542
|
-
? `/sap/bc/adt/atc/worklists?checkVariant=${encodeURIComponent(variant)}`
|
|
543
|
-
: '/sap/bc/adt/atc/worklists';
|
|
544
|
-
const worklistResp = await http.post(worklistPath, '', 'application/xml', { Accept: 'text/plain' });
|
|
545
|
-
const worklistId = worklistResp.body.trim();
|
|
546
|
-
if (!worklistId) {
|
|
547
|
-
throw new AdtApiError('ATC worklist creation returned no worklist id; cannot run ATC checks.', 500, worklistPath);
|
|
548
|
-
}
|
|
549
|
-
// Step 2 — run the selected checks for the object set into that worklist.
|
|
550
|
-
const runBody = `<?xml version="1.0" encoding="UTF-8"?>
|
|
551
|
-
<atc:run xmlns:atc="http://www.sap.com/adt/atc" maximumVerdicts="100">
|
|
552
|
-
<objectSets xmlns:adtcore="http://www.sap.com/adt/core">
|
|
553
|
-
<objectSet kind="inclusive">
|
|
554
|
-
<adtcore:objectReferences>
|
|
555
|
-
<adtcore:objectReference adtcore:uri="${escapeXmlAttr(objectUrl)}"/>
|
|
556
|
-
</adtcore:objectReferences>
|
|
557
|
-
</objectSet>
|
|
558
|
-
</objectSets>
|
|
559
|
-
</atc:run>`;
|
|
560
|
-
await http.post(`/sap/bc/adt/atc/runs?worklistId=${encodeURIComponent(worklistId)}`, runBody, 'application/xml', {
|
|
561
|
-
Accept: 'application/xml',
|
|
562
|
-
});
|
|
563
|
-
// Step 3 — read the populated worklist with its findings.
|
|
564
|
-
const resultResp = await http.get(`/sap/bc/adt/atc/worklists/${encodeURIComponent(worklistId)}`, {
|
|
565
|
-
Accept: 'application/atc.worklist.v1+xml',
|
|
566
|
-
});
|
|
567
|
-
return { findings: parseAtcFindings(resultResp.body) };
|
|
568
|
-
}
|
|
569
525
|
/**
|
|
570
526
|
* Get SAP-suggested ABAP Unit test cases for a CDS entity (CDS Test Double Framework).
|
|
571
527
|
*
|
|
@@ -806,116 +762,18 @@ function parseSyntaxCheckResult(xml) {
|
|
|
806
762
|
...(uri ? { uri } : {}),
|
|
807
763
|
};
|
|
808
764
|
});
|
|
765
|
+
// SAP reports refusal to check via <chkrun:checkReport chkrun:status="notProcessed"
|
|
766
|
+
// chkrun:statusText="Resource CLASS ZCL_X does not exist."/> — with zero messages, which would
|
|
767
|
+
// otherwise read as "clean". Legacy <msg> shapes carry no report → treat as checked.
|
|
768
|
+
const reports = findDeepNodes(parsed, 'checkReport');
|
|
769
|
+
const unprocessed = reports.find((r) => r['@_status'] && String(r['@_status']) !== 'processed');
|
|
809
770
|
return {
|
|
810
771
|
hasErrors: messages.some((m) => m.severity === 'error'),
|
|
811
772
|
messages,
|
|
773
|
+
checked: !unprocessed,
|
|
774
|
+
...(unprocessed ? { statusText: decodeXmlEntities(String(unprocessed['@_statusText'] ?? '')) } : {}),
|
|
812
775
|
};
|
|
813
776
|
}
|
|
814
|
-
/** Extract the human-readable title from an AUnit alert node (string or #text object). */
|
|
815
|
-
function alertTitle(alert) {
|
|
816
|
-
const titleVal = alert.title;
|
|
817
|
-
if (titleVal == null)
|
|
818
|
-
return '';
|
|
819
|
-
if (typeof titleVal === 'string')
|
|
820
|
-
return titleVal;
|
|
821
|
-
if (typeof titleVal === 'object' && !Array.isArray(titleVal)) {
|
|
822
|
-
return String(titleVal['#text'] ?? '');
|
|
823
|
-
}
|
|
824
|
-
return String(titleVal);
|
|
825
|
-
}
|
|
826
|
-
/** Flatten `<details><detail text="…">`, which nests further on some releases. The nested texts
|
|
827
|
-
* carry the payload ("Expected [2] Actual [1]"); the title alone is often generic. */
|
|
828
|
-
function alertDetails(node) {
|
|
829
|
-
const texts = [];
|
|
830
|
-
for (const detail of getNestedArray(node, 'details', 'detail')) {
|
|
831
|
-
const text = String(detail['@_text'] ?? '').trim();
|
|
832
|
-
if (text)
|
|
833
|
-
texts.push(text);
|
|
834
|
-
texts.push(...alertDetails(detail));
|
|
835
|
-
}
|
|
836
|
-
return texts;
|
|
837
|
-
}
|
|
838
|
-
/** Title + details, entity-decoded (the shared parser runs with `processEntities: false`). */
|
|
839
|
-
function alertMessage(alert) {
|
|
840
|
-
const parts = [alertTitle(alert), ...alertDetails(alert)].filter(Boolean);
|
|
841
|
-
return parts.length > 0 ? decodeXmlEntities(parts.join(' — ')) : undefined;
|
|
842
|
-
}
|
|
843
|
-
/** `severity="tolerable"` means SAP declined to run the test ("risk level of test class exceeds
|
|
844
|
-
* upper limit"), NOT that it failed — reporting those as failures sends the caller after a
|
|
845
|
-
* phantom bug. Anything else (critical/fatal) is a real failure. */
|
|
846
|
-
function alertStatus(alerts) {
|
|
847
|
-
return alerts.some((a) => a['@_severity'] !== 'tolerable') ? 'failed' : 'skipped';
|
|
848
|
-
}
|
|
849
|
-
/** One row for one alert that has no test method to hang off (run, program or class level). */
|
|
850
|
-
function alertRow(program, testClass, testMethod, alert) {
|
|
851
|
-
const message = alertMessage(alert);
|
|
852
|
-
return { program, testClass, testMethod, status: alertStatus([alert]), ...(message ? { message } : {}) };
|
|
853
|
-
}
|
|
854
|
-
/**
|
|
855
|
-
* Parse an `abapunit/testruns` result.
|
|
856
|
-
*
|
|
857
|
-
* Walks the response structure — `runResult → program → testClasses → testClass → testMethods →
|
|
858
|
-
* testMethod`, each level carrying its own optional `alerts` — rather than searching the tree for
|
|
859
|
-
* `testMethod` nodes. Two reasons, both live-verified on 7.50 / 7.58 / 8.16:
|
|
860
|
-
* - an alert at run, program or class level is the ONLY record of why a run produced no methods
|
|
861
|
-
* (CLASS_SETUP dump, generation failure, risk level above the client ceiling);
|
|
862
|
-
* - the program name must come from `<program adtcore:name>`, because the testClass URI it used
|
|
863
|
-
* to be parsed from is release-dependent (7.50 `…/includes/testclasses#start=7,6`
|
|
864
|
-
* vs 758/816 `…#testclass=LTCL_X`).
|
|
865
|
-
*/
|
|
866
|
-
function parseUnitTestResults(xml) {
|
|
867
|
-
const results = [];
|
|
868
|
-
const runResult = (parseXml(xml).runResult ?? {});
|
|
869
|
-
for (const alert of getNestedArray(runResult, 'alerts', 'alert')) {
|
|
870
|
-
results.push(alertRow('', '(run)', '(alert)', alert));
|
|
871
|
-
}
|
|
872
|
-
for (const program of asNodeArray(runResult.program)) {
|
|
873
|
-
const programName = String(program['@_name'] ?? '');
|
|
874
|
-
for (const alert of getNestedArray(program, 'alerts', 'alert')) {
|
|
875
|
-
results.push(alertRow(programName, '(program)', '(alert)', alert));
|
|
876
|
-
}
|
|
877
|
-
for (const tc of getNestedArray(program, 'testClasses', 'testClass')) {
|
|
878
|
-
const className = String(tc['@_name'] ?? '');
|
|
879
|
-
const classAlerts = getNestedArray(tc, 'alerts', 'alert');
|
|
880
|
-
const methods = getNestedArray(tc, 'testMethods', 'testMethod');
|
|
881
|
-
// A class that aborted in CLASS_SETUP, or that SAP declined to run, reports alerts here and
|
|
882
|
-
// no methods at all — the shape that used to vanish from the result.
|
|
883
|
-
for (const alert of classAlerts) {
|
|
884
|
-
results.push(alertRow(programName, className, '(class-level alert)', alert));
|
|
885
|
-
}
|
|
886
|
-
for (const method of methods) {
|
|
887
|
-
const alerts = getNestedArray(method, 'alerts', 'alert');
|
|
888
|
-
const message = alerts.length > 0 ? alertMessage(alerts[0]) : undefined;
|
|
889
|
-
const execTime = method['@_executionTime'];
|
|
890
|
-
const duration = execTime ? Number(execTime) : undefined;
|
|
891
|
-
results.push({
|
|
892
|
-
program: programName,
|
|
893
|
-
testClass: className,
|
|
894
|
-
testMethod: String(method['@_name'] ?? ''),
|
|
895
|
-
status: alerts.length > 0 ? alertStatus(alerts) : 'passed',
|
|
896
|
-
...(message ? { message } : {}),
|
|
897
|
-
...(duration !== undefined && !Number.isNaN(duration) ? { duration } : {}),
|
|
898
|
-
});
|
|
899
|
-
}
|
|
900
|
-
if (classAlerts.length === 0 && methods.length === 0) {
|
|
901
|
-
results.push({
|
|
902
|
-
program: programName,
|
|
903
|
-
testClass: className,
|
|
904
|
-
testMethod: '(class-level alert)',
|
|
905
|
-
status: 'skipped',
|
|
906
|
-
message: 'test class reported no test methods and no alert',
|
|
907
|
-
});
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
return results;
|
|
912
|
-
}
|
|
913
|
-
/** One-or-many node → array (`program` is not an ARRAY_TAG, so a single one parses as an object). */
|
|
914
|
-
function asNodeArray(value) {
|
|
915
|
-
if (Array.isArray(value))
|
|
916
|
-
return value;
|
|
917
|
-
return value && typeof value === 'object' ? [value] : [];
|
|
918
|
-
}
|
|
919
777
|
function toNodeRecord(value) {
|
|
920
778
|
if (!value)
|
|
921
779
|
return undefined;
|
|
@@ -1102,41 +960,6 @@ function parseFixDeltas(xml) {
|
|
|
1102
960
|
}
|
|
1103
961
|
return nodes.map(parseFixDeltaNode);
|
|
1104
962
|
}
|
|
1105
|
-
function parseAtcFindings(xml) {
|
|
1106
|
-
const parsed = parseXml(xml);
|
|
1107
|
-
const nodes = findDeepNodes(parsed, 'finding');
|
|
1108
|
-
return nodes.map((f) => {
|
|
1109
|
-
// Real ATC findings carry TWO uri-ish attributes: `adtcore:uri` (a findings-catalog
|
|
1110
|
-
// URI with no source position) and `atcfinding:location` (the source URI with the
|
|
1111
|
-
// `#start=line,col` fragment). Prefer `location` so the source line is extracted and
|
|
1112
|
-
// the returned uri points at the actual code position. Hand-written fixtures that only
|
|
1113
|
-
// set `uri="...#start=..."` still work via the fallback.
|
|
1114
|
-
const rawUri = String(f['@_location'] ?? f['@_uri'] ?? '');
|
|
1115
|
-
let line = 0;
|
|
1116
|
-
const startIdx = rawUri.indexOf('#start=');
|
|
1117
|
-
if (startIdx !== -1) {
|
|
1118
|
-
const fragment = rawUri.slice(startIdx + '#start='.length);
|
|
1119
|
-
const firstNum = Number.parseInt(fragment.split(',')[0], 10);
|
|
1120
|
-
if (!Number.isNaN(firstNum))
|
|
1121
|
-
line = firstNum;
|
|
1122
|
-
}
|
|
1123
|
-
const quickfixInfoRaw = f['@_quickfixInfo'];
|
|
1124
|
-
const quickfixInfo = quickfixInfoRaw == null ? undefined : String(quickfixInfoRaw);
|
|
1125
|
-
const quickfixNode = toNodeRecord(f.quickfixes);
|
|
1126
|
-
const manual = String(quickfixNode?.['@_manual'] ?? 'false').toLowerCase() === 'true';
|
|
1127
|
-
const automatic = String(quickfixNode?.['@_automatic'] ?? 'false').toLowerCase() === 'true';
|
|
1128
|
-
const pseudo = String(quickfixNode?.['@_pseudo'] ?? 'false').toLowerCase() === 'true';
|
|
1129
|
-
return {
|
|
1130
|
-
priority: Number.parseInt(String(f['@_priority'] ?? '0'), 10),
|
|
1131
|
-
checkTitle: String(f['@_checkTitle'] ?? ''),
|
|
1132
|
-
messageTitle: String(f['@_messageTitle'] ?? ''),
|
|
1133
|
-
uri: rawUri,
|
|
1134
|
-
line,
|
|
1135
|
-
quickfixInfo,
|
|
1136
|
-
hasQuickfix: manual || automatic || pseudo,
|
|
1137
|
-
};
|
|
1138
|
-
});
|
|
1139
|
-
}
|
|
1140
963
|
/** Read the text content of a CDS test-case child element (string leaf or {#text} node). */
|
|
1141
964
|
function cdsNodeText(v) {
|
|
1142
965
|
if (v == null)
|