@nudojs/core 1.14.0 → 1.14.1
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/dist/{chunk-N7AGFMSD.js → chunk-4GZPH6YL.js} +398 -2
- package/dist/{chunk-W3Z77Y2I.js → chunk-JMOQEJTD.js} +14552 -14200
- package/dist/exec.d.ts +206 -57
- package/dist/exec.js +1 -1
- package/dist/index.d.ts +141 -8
- package/dist/index.js +21 -358
- package/dist/internal.d.ts +21 -5
- package/dist/internal.js +6 -2
- package/dist/{projection-budget-DPPRBOLp.d.ts → projection-budget-07VnMktV.d.ts} +44 -2
- package/dist/{run-DhSqP3in.d.ts → run-DfloWX6i.d.ts} +9 -0
- package/package.json +1 -1
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
withEvalBudgetOverride,
|
|
48
48
|
withExecPhi,
|
|
49
49
|
withFnBudgetOverride
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-JMOQEJTD.js";
|
|
51
51
|
|
|
52
52
|
// src/algebra/directive-scan.ts
|
|
53
53
|
function cleanDirectiveLine(raw, kind) {
|
|
@@ -5570,6 +5570,395 @@ function scanLiteralCalls(source, knownFns, phi, opts) {
|
|
|
5570
5570
|
return out;
|
|
5571
5571
|
}
|
|
5572
5572
|
|
|
5573
|
+
// src/algebra/check-report.ts
|
|
5574
|
+
function actionsForIssue(i) {
|
|
5575
|
+
const draft = {
|
|
5576
|
+
kind: "draft",
|
|
5577
|
+
command: "nudo contract --draft",
|
|
5578
|
+
label: "emit a sidecar draft you can edit"
|
|
5579
|
+
};
|
|
5580
|
+
switch (i.code) {
|
|
5581
|
+
case "nudo:constraint-violated":
|
|
5582
|
+
return [
|
|
5583
|
+
{
|
|
5584
|
+
kind: "callsite",
|
|
5585
|
+
label: "use a value satisfying the constraint",
|
|
5586
|
+
...i.expected ? { hint: i.expected } : {}
|
|
5587
|
+
},
|
|
5588
|
+
{
|
|
5589
|
+
kind: "relax",
|
|
5590
|
+
label: "relax the precondition (edit *.nudo.js / @nudo:contract)",
|
|
5591
|
+
...i.expected ? { hint: i.expected } : {}
|
|
5592
|
+
},
|
|
5593
|
+
draft
|
|
5594
|
+
];
|
|
5595
|
+
case "nudo:assign-mismatch":
|
|
5596
|
+
return [
|
|
5597
|
+
{
|
|
5598
|
+
kind: "callsite",
|
|
5599
|
+
label: "align the assigned value with the existing shape",
|
|
5600
|
+
...i.expected ? { hint: i.expected } : {}
|
|
5601
|
+
},
|
|
5602
|
+
draft
|
|
5603
|
+
];
|
|
5604
|
+
case "nudo:entry-may-throw":
|
|
5605
|
+
return [
|
|
5606
|
+
{
|
|
5607
|
+
kind: "draft",
|
|
5608
|
+
command: "nudo contract --draft",
|
|
5609
|
+
label: "narrow the entry with a sidecar fn({ \u2026 }) param contract \u2014 most honest fix for helpers (also tightens the signature)",
|
|
5610
|
+
...i.fn ? { hint: i.fn } : {}
|
|
5611
|
+
},
|
|
5612
|
+
{
|
|
5613
|
+
kind: "relax",
|
|
5614
|
+
label: "declare intentional fail-fast: @nudo:throws Error (or case `!! throws`)",
|
|
5615
|
+
...i.fn ? { hint: i.fn } : {}
|
|
5616
|
+
},
|
|
5617
|
+
{
|
|
5618
|
+
kind: "info",
|
|
5619
|
+
label: "or refine / guard / try-catch the entry so it is total"
|
|
5620
|
+
},
|
|
5621
|
+
{
|
|
5622
|
+
kind: "ignore-throws",
|
|
5623
|
+
command: "nudo check --ignore-throws TypeError",
|
|
5624
|
+
label: "migration switch: ignore this throw class on L2"
|
|
5625
|
+
}
|
|
5626
|
+
];
|
|
5627
|
+
case "nudo:unproven-return":
|
|
5628
|
+
return [
|
|
5629
|
+
{
|
|
5630
|
+
kind: "relax",
|
|
5631
|
+
label: `relax the return contract${i.fn ? ` of ${i.fn}` : ""} to the inferred surface (review the diff \u2014 not a silent green)`,
|
|
5632
|
+
...i.expected ? { hint: i.expected } : {}
|
|
5633
|
+
},
|
|
5634
|
+
draft,
|
|
5635
|
+
{
|
|
5636
|
+
kind: "info",
|
|
5637
|
+
label: "or narrow the return expression / add a precondition so the bound is implied"
|
|
5638
|
+
}
|
|
5639
|
+
];
|
|
5640
|
+
case "nudo:unknown-inference":
|
|
5641
|
+
case "nudo:opaque-result":
|
|
5642
|
+
return [
|
|
5643
|
+
{ kind: "mock", label: "pin the native/unknown face with @nudo:mock" },
|
|
5644
|
+
{ kind: "assume", command: "nudo check --assume", label: "state preconditions via --assume" },
|
|
5645
|
+
{ kind: "info", label: "or add a call site / @nudo:case for evidence" }
|
|
5646
|
+
];
|
|
5647
|
+
case "nudo:arg-opaque":
|
|
5648
|
+
case "nudo:constraint-unproven":
|
|
5649
|
+
return [
|
|
5650
|
+
{ kind: "assume", command: "nudo check --assume", label: "state preconditions via --assume" },
|
|
5651
|
+
{ kind: "info", label: "add a call site or @nudo:case" }
|
|
5652
|
+
];
|
|
5653
|
+
case "nudo:fork-truncated":
|
|
5654
|
+
case "nudo:promise-micro-truncated":
|
|
5655
|
+
case "nudo:promise-micro-error":
|
|
5656
|
+
return [
|
|
5657
|
+
{
|
|
5658
|
+
kind: "info",
|
|
5659
|
+
label: "results widened to unknown \u2014 raise budget (@nudo:budget forks/calls/depth on the function) or narrow control flow"
|
|
5660
|
+
}
|
|
5661
|
+
];
|
|
5662
|
+
case "nudo:loop-truncated":
|
|
5663
|
+
return [
|
|
5664
|
+
{
|
|
5665
|
+
kind: "info",
|
|
5666
|
+
label: "loop state widened \u2014 the exit condition stayed concrete-true past the iteration cap; make the bound data-dependent (abstract) or pin the result with @nudo:case / @nudo:contract"
|
|
5667
|
+
}
|
|
5668
|
+
];
|
|
5669
|
+
case "nudo:recursion-truncated":
|
|
5670
|
+
return [
|
|
5671
|
+
{
|
|
5672
|
+
kind: "info",
|
|
5673
|
+
label: i.reason === "cycle" ? "call cycle: same abstract arguments already on the stack \u2014 raising @nudo:budget cannot lift it; make the arguments vary per recursion level or declare @nudo:contract" : i.reason === "depth" || i.reason === "calls" || i.reason === "budget" ? `results widened to unknown \u2014 raise budget (@nudo:budget ${i.reason === "depth" ? "depth" : i.reason === "calls" ? "calls" : "calls/depth"} on the function) or narrow the recursion` : "results widened to unknown \u2014 raise budget (@nudo:budget calls/depth on the function) or narrow control flow"
|
|
5674
|
+
}
|
|
5675
|
+
];
|
|
5676
|
+
case "nudo:host-effect-blocked":
|
|
5677
|
+
return [
|
|
5678
|
+
{ kind: "mock", label: "pin the host API with @nudo:mock / @nudo:env" },
|
|
5679
|
+
{ kind: "info", label: "results widened to unknown \u2014 or feed the value in from a call site" }
|
|
5680
|
+
];
|
|
5681
|
+
case "nudo:interface-drift":
|
|
5682
|
+
return [
|
|
5683
|
+
{
|
|
5684
|
+
kind: "emit",
|
|
5685
|
+
command: "nudo contract --emit",
|
|
5686
|
+
label: "refresh the @generated segment"
|
|
5687
|
+
}
|
|
5688
|
+
];
|
|
5689
|
+
case "nudo:dual-entry":
|
|
5690
|
+
return [
|
|
5691
|
+
{
|
|
5692
|
+
kind: "info",
|
|
5693
|
+
label: "browser/node records do not cross files \u2014 analyze the entry you ship; mock or skip the other variant"
|
|
5694
|
+
}
|
|
5695
|
+
];
|
|
5696
|
+
default:
|
|
5697
|
+
return i.suggestion ? [{ kind: "info", label: i.suggestion }] : [];
|
|
5698
|
+
}
|
|
5699
|
+
}
|
|
5700
|
+
function serializeCheckJson(r) {
|
|
5701
|
+
return {
|
|
5702
|
+
version: 1,
|
|
5703
|
+
file: r.file,
|
|
5704
|
+
ok: r.ok,
|
|
5705
|
+
summary: { ...r.summary },
|
|
5706
|
+
signatures: r.signatures.map((s) => ({
|
|
5707
|
+
name: s.name,
|
|
5708
|
+
params: [...s.params],
|
|
5709
|
+
...s.paramTypes ? { paramTypes: [...s.paramTypes] } : {},
|
|
5710
|
+
display: s.display,
|
|
5711
|
+
detail: s.detail,
|
|
5712
|
+
conf: s.conf,
|
|
5713
|
+
abs: formatAbs(s.abs),
|
|
5714
|
+
...s.throws ? { throws: s.throws } : {},
|
|
5715
|
+
...s.entry ? { entry: true } : {}
|
|
5716
|
+
})),
|
|
5717
|
+
issues: r.issues.map((i) => {
|
|
5718
|
+
const acts = i.actions ?? actionsForIssue(i);
|
|
5719
|
+
return {
|
|
5720
|
+
severity: i.severity,
|
|
5721
|
+
code: i.code,
|
|
5722
|
+
message: i.message,
|
|
5723
|
+
...i.fn !== void 0 ? { fn: i.fn } : {},
|
|
5724
|
+
...i.line !== void 0 ? { line: i.line } : {},
|
|
5725
|
+
...i.column !== void 0 ? { column: i.column } : {},
|
|
5726
|
+
...i.actual !== void 0 ? { actual: i.actual } : {},
|
|
5727
|
+
...i.expected !== void 0 ? { expected: i.expected } : {},
|
|
5728
|
+
...i.suggestion !== void 0 ? { suggestion: i.suggestion } : {},
|
|
5729
|
+
...i.reason !== void 0 ? { reason: i.reason } : {},
|
|
5730
|
+
...acts.length > 0 ? { actions: acts } : {}
|
|
5731
|
+
};
|
|
5732
|
+
}),
|
|
5733
|
+
...r.budget ? { budget: { ...r.budget } } : {}
|
|
5734
|
+
};
|
|
5735
|
+
}
|
|
5736
|
+
function serializeCheckJsonMulti(reports) {
|
|
5737
|
+
const summary = {
|
|
5738
|
+
errors: 0,
|
|
5739
|
+
warnings: 0,
|
|
5740
|
+
infos: 0,
|
|
5741
|
+
functions: 0,
|
|
5742
|
+
files: reports.length
|
|
5743
|
+
};
|
|
5744
|
+
let calls = 0;
|
|
5745
|
+
let forks = 0;
|
|
5746
|
+
let maxCalls = 0;
|
|
5747
|
+
let maxForks = 0;
|
|
5748
|
+
let callTruncated = false;
|
|
5749
|
+
let forkTruncated = false;
|
|
5750
|
+
let evalCalls = 0;
|
|
5751
|
+
let maxEvalCalls = 0;
|
|
5752
|
+
let evalCallTruncated = false;
|
|
5753
|
+
let cycleTruncated = false;
|
|
5754
|
+
let loopTruncated = false;
|
|
5755
|
+
const callReasons = /* @__PURE__ */ new Set();
|
|
5756
|
+
const evalReasons = /* @__PURE__ */ new Set();
|
|
5757
|
+
let depth = 0;
|
|
5758
|
+
let maxDepth = 0;
|
|
5759
|
+
let evalDepth = 0;
|
|
5760
|
+
let maxEvalDepth = 0;
|
|
5761
|
+
const reasons = /* @__PURE__ */ new Set();
|
|
5762
|
+
for (const r of reports) {
|
|
5763
|
+
summary.errors += r.summary.errors;
|
|
5764
|
+
summary.warnings += r.summary.warnings;
|
|
5765
|
+
summary.infos += r.summary.infos;
|
|
5766
|
+
summary.functions += r.summary.functions;
|
|
5767
|
+
if (r.budget) {
|
|
5768
|
+
calls += r.budget.calls;
|
|
5769
|
+
forks += r.budget.forks;
|
|
5770
|
+
maxCalls = Math.max(maxCalls, r.budget.maxCalls);
|
|
5771
|
+
maxForks = Math.max(maxForks, r.budget.maxForks);
|
|
5772
|
+
callTruncated = callTruncated || r.budget.callTruncated;
|
|
5773
|
+
forkTruncated = forkTruncated || r.budget.forkTruncated;
|
|
5774
|
+
evalCalls += r.budget.evalCalls ?? 0;
|
|
5775
|
+
maxEvalCalls = Math.max(maxEvalCalls, r.budget.maxEvalCalls ?? 0);
|
|
5776
|
+
evalCallTruncated = evalCallTruncated || (r.budget.evalCallTruncated ?? false);
|
|
5777
|
+
cycleTruncated = cycleTruncated || (r.budget.cycleTruncated ?? false);
|
|
5778
|
+
loopTruncated = loopTruncated || (r.budget.loopTruncated ?? false);
|
|
5779
|
+
for (const x of r.budget.callReasons ?? []) callReasons.add(x);
|
|
5780
|
+
for (const x of r.budget.evalReasons ?? []) evalReasons.add(x);
|
|
5781
|
+
depth = Math.max(depth, r.budget.depth ?? 0);
|
|
5782
|
+
maxDepth = Math.max(maxDepth, r.budget.maxDepth ?? 0);
|
|
5783
|
+
evalDepth = Math.max(evalDepth, r.budget.evalDepth ?? 0);
|
|
5784
|
+
maxEvalDepth = Math.max(maxEvalDepth, r.budget.maxEvalDepth ?? 0);
|
|
5785
|
+
for (const x of r.budget.reasons ?? []) reasons.add(x);
|
|
5786
|
+
}
|
|
5787
|
+
}
|
|
5788
|
+
const budgetTruncated = callTruncated || evalCallTruncated || forkTruncated || loopTruncated;
|
|
5789
|
+
return {
|
|
5790
|
+
version: 1,
|
|
5791
|
+
kind: "multi",
|
|
5792
|
+
ok: reports.every((r) => r.ok),
|
|
5793
|
+
summary: {
|
|
5794
|
+
...summary,
|
|
5795
|
+
...budgetTruncated ? { budgetTruncated: true } : {}
|
|
5796
|
+
},
|
|
5797
|
+
...budgetTruncated || reports.some((r) => r.budget) ? {
|
|
5798
|
+
budget: {
|
|
5799
|
+
truncated: budgetTruncated,
|
|
5800
|
+
callTruncated,
|
|
5801
|
+
forkTruncated,
|
|
5802
|
+
calls,
|
|
5803
|
+
maxCalls,
|
|
5804
|
+
forks,
|
|
5805
|
+
maxForks,
|
|
5806
|
+
evalCalls,
|
|
5807
|
+
maxEvalCalls,
|
|
5808
|
+
evalCallTruncated,
|
|
5809
|
+
cycleTruncated,
|
|
5810
|
+
loopTruncated,
|
|
5811
|
+
callReasons: [...callReasons].sort(),
|
|
5812
|
+
depth,
|
|
5813
|
+
maxDepth,
|
|
5814
|
+
evalReasons: [...evalReasons].sort(),
|
|
5815
|
+
evalDepth,
|
|
5816
|
+
maxEvalDepth,
|
|
5817
|
+
reasons: [...reasons].sort()
|
|
5818
|
+
}
|
|
5819
|
+
} : {},
|
|
5820
|
+
reports
|
|
5821
|
+
};
|
|
5822
|
+
}
|
|
5823
|
+
var CONTRACT_FIX_CODES = /* @__PURE__ */ new Set([
|
|
5824
|
+
"nudo:constraint-violated",
|
|
5825
|
+
"nudo:assign-mismatch",
|
|
5826
|
+
"nudo:arg-structure",
|
|
5827
|
+
"nudo:interface-domain-exceeds",
|
|
5828
|
+
"nudo:entry-may-throw",
|
|
5829
|
+
"nudo:missing-slot"
|
|
5830
|
+
]);
|
|
5831
|
+
function budgetAttributionSegs(b) {
|
|
5832
|
+
const segs = [];
|
|
5833
|
+
if ((b.callReasons ?? []).includes("calls")) segs.push(`calls ${b.calls}/${b.maxCalls}`);
|
|
5834
|
+
if ((b.callReasons ?? []).includes("depth")) segs.push(`call depth ${b.depth}/${b.maxDepth}`);
|
|
5835
|
+
if ((b.evalReasons ?? []).includes("calls")) {
|
|
5836
|
+
segs.push(`eval calls ${b.evalCalls}/${b.maxEvalCalls}`);
|
|
5837
|
+
}
|
|
5838
|
+
if ((b.evalReasons ?? []).includes("depth")) {
|
|
5839
|
+
segs.push(`eval depth ${b.evalDepth}/${b.maxEvalDepth}`);
|
|
5840
|
+
}
|
|
5841
|
+
if (b.forkTruncated) segs.push(`forks ${b.forks}/${b.maxForks}`);
|
|
5842
|
+
if (b.loopTruncated) segs.push("loop iterations");
|
|
5843
|
+
const cycleOnly = segs.length === 0;
|
|
5844
|
+
if (cycleOnly) segs.push("call cycle \u2014 not a budget limit");
|
|
5845
|
+
return { segs, cycleOnly };
|
|
5846
|
+
}
|
|
5847
|
+
function formatCheckReport(r, opts = {}) {
|
|
5848
|
+
const lines = [];
|
|
5849
|
+
lines.push(`nudo check ${r.file}`);
|
|
5850
|
+
lines.push(r.ok ? "OK" : "FAILED");
|
|
5851
|
+
lines.push(
|
|
5852
|
+
` ${r.summary.errors} error \xB7 ${r.summary.warnings} warning \xB7 ${r.summary.infos} info \xB7 ${r.summary.functions} fn`
|
|
5853
|
+
);
|
|
5854
|
+
if (r.budget?.truncated) {
|
|
5855
|
+
const b = r.budget;
|
|
5856
|
+
const onlyLoop = b.loopTruncated && !b.callTruncated && !b.evalCallTruncated && !b.forkTruncated;
|
|
5857
|
+
const { segs } = budgetAttributionSegs(b);
|
|
5858
|
+
lines.push("");
|
|
5859
|
+
lines.push("budget");
|
|
5860
|
+
lines.push(` truncated ${segs.join(" \xB7 ")}`);
|
|
5861
|
+
lines.push(
|
|
5862
|
+
r.budget.cycleTruncated ? ` \u2192 some results widened to unknown (not a contract failure) \u2014 includes call cycles (same abstract args; a budget cannot lift them)` : onlyLoop ? ` \u2192 loop state widened (iteration budget, not a contract failure) \u2014 @nudo:budget does not apply; make the bound data-dependent or pin with @nudo:case / @nudo:contract` : ` \u2192 some results widened to unknown (not a contract failure) \u2014 raise @nudo:budget / nudo.analysis.maxForks or simplify recursion`
|
|
5863
|
+
);
|
|
5864
|
+
}
|
|
5865
|
+
if (r.signatures.length > 0) {
|
|
5866
|
+
lines.push("");
|
|
5867
|
+
lines.push("signatures");
|
|
5868
|
+
for (const s of r.signatures) {
|
|
5869
|
+
const paramStr = s.paramTypes && s.paramTypes.length > 0 ? s.params.map((p, i) => `${p}: ${s.paramTypes[i] ?? "any"}`).join(", ") : s.params.join(", ");
|
|
5870
|
+
const throwsStr = s.throws ? ` throws ${s.throws}` : "";
|
|
5871
|
+
const displayBase = s.display.replace(/\s+throws\s+[\s\S]+$/, "").trim();
|
|
5872
|
+
const shapeK = s.abs?.shape?.k;
|
|
5873
|
+
const looksLikeFakeAny = shapeK === "any" && displayBase.length > 0 && !/^any(\b|$)/.test(displayBase);
|
|
5874
|
+
const retStr = !looksLikeFakeAny && shapeK ? formatShape(s.abs) || displayBase.replace(/\s+#\w+$/, "").trim() : displayBase.replace(/\s+#\w+$/, "").trim();
|
|
5875
|
+
lines.push(` ${s.name}(${paramStr}) => ${retStr}${throwsStr}`);
|
|
5876
|
+
if (opts.verbose) {
|
|
5877
|
+
for (const ln of s.detail.split("\n").slice(1)) {
|
|
5878
|
+
lines.push(` ${ln}`);
|
|
5879
|
+
}
|
|
5880
|
+
}
|
|
5881
|
+
}
|
|
5882
|
+
}
|
|
5883
|
+
if (r.issues.length === 0) {
|
|
5884
|
+
lines.push("");
|
|
5885
|
+
lines.push("(no issues)");
|
|
5886
|
+
} else {
|
|
5887
|
+
lines.push("");
|
|
5888
|
+
lines.push("issues");
|
|
5889
|
+
for (const i of r.issues) {
|
|
5890
|
+
const loc = i.line != null ? `L${i.line}` : "";
|
|
5891
|
+
const head = [i.severity.toUpperCase(), loc, i.fn].filter(Boolean).join(" ");
|
|
5892
|
+
lines.push(` [${head}] ${i.message} (${i.code})`);
|
|
5893
|
+
const showDetail = i.severity === "error" || opts.verbose;
|
|
5894
|
+
if (showDetail && i.actual) lines.push(` actual: ${i.actual}`);
|
|
5895
|
+
if (showDetail && i.expected) lines.push(` expected: ${i.expected}`);
|
|
5896
|
+
if (i.suggestion) {
|
|
5897
|
+
lines.push(` \u2192 ${i.suggestion}`);
|
|
5898
|
+
} else if (CONTRACT_FIX_CODES.has(i.code)) {
|
|
5899
|
+
lines.push(` \u2192 add a refine / sidecar contract, or fix the call-site value`);
|
|
5900
|
+
}
|
|
5901
|
+
if (CONTRACT_FIX_CODES.has(i.code)) {
|
|
5902
|
+
lines.push(` fix: nudo contract --draft (emit a sidecar draft you can edit)`);
|
|
5903
|
+
}
|
|
5904
|
+
}
|
|
5905
|
+
}
|
|
5906
|
+
return lines.join("\n");
|
|
5907
|
+
}
|
|
5908
|
+
function escapeGhaData(s) {
|
|
5909
|
+
return s.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A");
|
|
5910
|
+
}
|
|
5911
|
+
function escapeGhaProp(s) {
|
|
5912
|
+
return escapeGhaData(s).replace(/:/g, "%3A").replace(/,/g, "%2C");
|
|
5913
|
+
}
|
|
5914
|
+
function formatGithubAnnotations(r, opts = {}) {
|
|
5915
|
+
const lines = [];
|
|
5916
|
+
let file = r.file;
|
|
5917
|
+
if (opts.workspaceRoot && file.startsWith(opts.workspaceRoot)) {
|
|
5918
|
+
file = file.slice(opts.workspaceRoot.length).replace(/^[/\\]/, "");
|
|
5919
|
+
}
|
|
5920
|
+
for (const i of r.issues) {
|
|
5921
|
+
const level = i.severity === "error" ? "error" : i.severity === "warning" ? "warning" : "notice";
|
|
5922
|
+
const line = i.line ?? 1;
|
|
5923
|
+
const col = (i.column ?? 0) + 1;
|
|
5924
|
+
const title = escapeGhaProp(i.code);
|
|
5925
|
+
const msgBits = [i.message];
|
|
5926
|
+
if (i.actual && i.expected) msgBits.push(`${i.actual} \u22AD ${i.expected}`);
|
|
5927
|
+
else if (i.suggestion) msgBits.push(i.suggestion);
|
|
5928
|
+
if (CONTRACT_FIX_CODES.has(i.code)) {
|
|
5929
|
+
msgBits.push(`fix: nudo contract --draft`);
|
|
5930
|
+
}
|
|
5931
|
+
const msg = escapeGhaData(msgBits.join(" \xB7 "));
|
|
5932
|
+
const props = [
|
|
5933
|
+
`file=${escapeGhaProp(file)}`,
|
|
5934
|
+
`line=${line}`,
|
|
5935
|
+
`col=${col}`,
|
|
5936
|
+
`title=${title}`
|
|
5937
|
+
].join(",");
|
|
5938
|
+
lines.push(`::${level} ${props}::${msg}`);
|
|
5939
|
+
}
|
|
5940
|
+
return lines.join("\n");
|
|
5941
|
+
}
|
|
5942
|
+
function formatGitlabCodeQuality(r, opts = {}) {
|
|
5943
|
+
let file = r.file;
|
|
5944
|
+
if (opts.workspaceRoot && file.startsWith(opts.workspaceRoot)) {
|
|
5945
|
+
file = file.slice(opts.workspaceRoot.length).replace(/^[/\\]/, "");
|
|
5946
|
+
}
|
|
5947
|
+
return r.issues.map((i) => {
|
|
5948
|
+
const begin = i.line ?? 1;
|
|
5949
|
+
const severity = i.severity === "error" ? "major" : i.severity === "warning" ? "minor" : "info";
|
|
5950
|
+
const description = i.actual && i.expected ? `${i.message} (${i.actual} \u22AD ${i.expected})` : i.message;
|
|
5951
|
+
const fingerprint = `${file}:${i.code}:${begin}:${i.message}`;
|
|
5952
|
+
return {
|
|
5953
|
+
description,
|
|
5954
|
+
check_name: i.code,
|
|
5955
|
+
fingerprint,
|
|
5956
|
+
severity,
|
|
5957
|
+
location: { path: file, lines: { begin } }
|
|
5958
|
+
};
|
|
5959
|
+
});
|
|
5960
|
+
}
|
|
5961
|
+
|
|
5573
5962
|
export {
|
|
5574
5963
|
listFnDirectiveScopes,
|
|
5575
5964
|
findFnDirectiveScope,
|
|
@@ -5648,5 +6037,12 @@ export {
|
|
|
5648
6037
|
stableAnalyzeKeySource,
|
|
5649
6038
|
listTopFunctions,
|
|
5650
6039
|
scanLiteralCalls,
|
|
5651
|
-
checkInjectedDomainEvidence
|
|
6040
|
+
checkInjectedDomainEvidence,
|
|
6041
|
+
actionsForIssue,
|
|
6042
|
+
serializeCheckJson,
|
|
6043
|
+
serializeCheckJsonMulti,
|
|
6044
|
+
budgetAttributionSegs,
|
|
6045
|
+
formatCheckReport,
|
|
6046
|
+
formatGithubAnnotations,
|
|
6047
|
+
formatGitlabCodeQuality
|
|
5652
6048
|
};
|