Skip to content

Commit 3ca4bde

Browse files
authored
Merge pull request #231 from PhysShell/claude/precision-quickwins-220-222-223-224
fix: close 4 precision gaps from the oracle sweep (#220, #222, #223, #224)
2 parents 0748800 + cd1c0ee commit 3ca4bde

6 files changed

Lines changed: 536 additions & 3 deletions

File tree

.github/workflows/ci.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ jobs:
207207
frontend/roslyn/samples/ReturnedPublisherSample.cs \
208208
frontend/roslyn/samples/OwnIgnoreSample.cs \
209209
frontend/roslyn/samples/DpRotationSample.cs \
210+
frontend/roslyn/samples/RequerySuggestedAllowlistSample.cs \
211+
frontend/roslyn/samples/SelfDetachingHandlerSample.cs \
212+
frontend/roslyn/samples/UsingFieldAcquisitionSample.cs \
213+
frontend/roslyn/samples/TemplatePartLocalCaptureSample.cs \
210214
-o "$RUNNER_TEMP/facts.json"
211215
cat "$RUNNER_TEMP/facts.json"
212216
- name: Check facts through the core
@@ -772,6 +776,65 @@ jobs:
772776
|| { echo "FAIL: a -=/+= pair on differently-typed params must stay flagged (not old/new halves)"; exit 1; }
773777
echo "$out" | grep -qE "\[OWN001\].*'TwoFieldsRotation'" \
774778
|| { echo "FAIL: a -=/+= pair across two class fields must stay flagged (not a rotation)"; exit 1; }
779+
# issue #223 — curated allowlist: CommandManager.RequerySuggested is implemented
780+
# over weak references (see docs/notes/field-notes-patterns.md entry 17), so an
781+
# ordinary instance-bound handler that never `-=`s it must NOT raise OWN014.
782+
if echo "$out" | grep -q "ImeSupportLike"; then
783+
echo "FAIL: an allowlisted CommandManager.RequerySuggested subscription was wrongly reported"; exit 1
784+
fi
785+
# control: an ORDINARY (non-allowlisted) static event, same never-detached
786+
# instance-handler shape, must STILL raise OWN014 — the allowlist must not
787+
# weaken the general static-source tier.
788+
echo "$out" | grep -qE "RequerySuggestedAllowlistSample\.cs:[0-9]+: error: \[OWN014\].*'OrdinaryStaticSubscriber'" \
789+
|| { echo "FAIL: expected OWN014 on the non-allowlisted static-event subscriber"; exit 1; }
790+
# issue #224 — a handler that unsubscribes ITSELF inside its own body (a
791+
# self-detaching one-shot handler) is bounded -> must be SILENT.
792+
if echo "$out" | grep -q "DropDownButtonLike"; then
793+
echo "FAIL: a self-detaching handler subscription was wrongly reported"; exit 1
794+
fi
795+
# control 1: the SAME shape but the handler does NOT self-detach -> must STILL warn.
796+
echo "$out" | grep -qE "SelfDetachingHandlerSample\.cs:[0-9]+: warning: \[OWN001\].*'NonDetachingSubscriber'" \
797+
|| { echo "FAIL: expected OWN001 on the non-self-detaching subscriber"; exit 1; }
798+
# control 2: the handler detaches a DIFFERENT event name -> must NOT be credited
799+
# as releasing the subscribed event -> must STILL warn.
800+
echo "$out" | grep -qE "SelfDetachingHandlerSample\.cs:[0-9]+: warning: \[OWN001\].*'WrongEventDetachSubscriber'" \
801+
|| { echo "FAIL: expected OWN001 when the self-detach targets the wrong event name"; exit 1; }
802+
# control 3 (Codex P2 on PR #231): the handler detaches the CORRECT event name
803+
# but off an UNRELATED receiver, not its own `sender` parameter -> the actual
804+
# subscribed source is never released -> must STILL warn.
805+
echo "$out" | grep -qE "SelfDetachingHandlerSample\.cs:[0-9]+: warning: \[OWN001\].*'WrongReceiverDetachSubscriber'" \
806+
|| { echo "FAIL: expected OWN001 when the self-detach targets the wrong receiver (not sender)"; exit 1; }
807+
# issue #220 — `using (field = new T())`: the field IS the `using` acquisition
808+
# target, disposed at scope exit -> must be SILENT.
809+
if echo "$out" | grep -q "HashCheckerLike"; then
810+
echo "FAIL: a field disposed via using (field = new T()) was wrongly reported"; exit 1
811+
fi
812+
# control: the SAME field, constructed the same way, but OUTSIDE any `using` and
813+
# never disposed -> must STILL warn (the recognition is using-scoped, not "any
814+
# field assignment from new is a release").
815+
echo "$out" | grep -qE "UsingFieldAcquisitionSample\.cs:[0-9]+: error: \[OWN001\].*'LeakyAssignerLike'" \
816+
|| { echo "FAIL: expected OWN001 on the field assigned outside any using block"; exit 1; }
817+
# issue #222 — a template part captured as a LOCAL (plain variable, via
818+
# Template.FindName) or an `is T x` PATTERN variable (via GetTemplateChild), not
819+
# only a field, is self-owned -> both must be SILENT.
820+
if echo "$out" | grep -qE "MetroWindowLike|OverloadViewerLike"; then
821+
echo "FAIL: a template part captured as a local/pattern variable was wrongly reported"; exit 1
822+
fi
823+
# control: a local variable that merely ALIASES an INJECTED field (not a
824+
# GetTemplateChild/FindName fetch) must STILL warn — the exemption is scoped to
825+
# an actual template-part fetch, not "any local-variable subscription is self-owned."
826+
echo "$out" | grep -qE "TemplatePartLocalCaptureSample\.cs:[0-9]+: warning: \[OWN001\].*'InjectedLocalSubscriber'" \
827+
|| { echo "FAIL: expected OWN001 on the injected-local (non-template-part) subscriber"; exit 1; }
828+
# control (Codex P2 on PR #231): a template-part local in one method must NOT
829+
# exempt an UNRELATED same-named local (aliasing an injected source) in a
830+
# DIFFERENT method of the same class — locals are self-owned by SYMBOL, not
831+
# name. The template-part method's own subscription must stay silent...
832+
if echo "$out" | grep -q "OnTemplateClick"; then
833+
echo "FAIL: the legitimate template-part-local subscription was wrongly reported"; exit 1
834+
fi
835+
# ...while the same-named local in the OTHER method must still warn.
836+
echo "$out" | grep -qE "TemplatePartLocalCaptureSample\.cs:[0-9]+: warning: \[OWN001\].*'SameNameDifferentScopeSubscriber'" \
837+
|| { echo "FAIL: expected OWN001 on the same-named-but-unrelated local in a different method"; exit 1; }
775838
echo "OK: real C# -> facts -> OWN001 (subscription + timer + field + Subscribe + pool + local) + OWN014 (static-event region escape) + DI001 (captive dependency) + DI002 (scoped captured weakly) + DI003 (transient IDisposable captured by a singleton) + DI004 (transient IDisposable service-located from the root provider) + DI005 (scoped service cached from a created scope) + [OwnIgnore] suppression (silent-but-counted, SARIF suppressions) + #218 DP old->new subscription rotation (silent; controls flagged) at the C# location"
776839
- name: Flow-sensitive local IDisposables (--flow-locals, P-016 B0b/B2)
777840
run: |

0 commit comments

Comments
 (0)