Skip to content

Commit 45a340d

Browse files
committed
feat(extractor): load extra reference assemblies via OWN_EXTRA_REF_DIRS (WPF unlock)
The extractor built its reference set purely from the runtime TPA, so WPF framework events/timers (Button.Click, DispatcherTimer.Tick) couldn't bind and fell out as OWN050 on real WPF apps — blinding the flagship subscription/timer detectors. Now it also loads *.dll from each dir in OWN_EXTRA_REF_DIRS (colon- separated), deduped by simple name against the TPA so System.* isn't double- referenced. Unset => unchanged behaviour (the whole existing suite is the guard). mine-on-push materializes the WindowsDesktop ref pack on Linux (a net8.0-windows /UseWPF stub restores it via EnableWindowsTargeting -> 47 ref dlls) and exports the dir as OWN_EXTRA_REF_DIRS. Re-mining ScreenToGif with the pack loaded. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rg8kSk1YT14x7A1vo5zgED
1 parent 5ef5652 commit 45a340d

3 files changed

Lines changed: 32 additions & 20 deletions

File tree

‎.github/workflows/mine-on-push.yml‎

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,12 @@ jobs:
3030
- uses: actions/setup-dotnet@v4
3131
with:
3232
dotnet-version: "8.0.x"
33-
- name: Probe WPF reference assemblies (TEMP — for the WPF unlock)
34-
continue-on-error: true
33+
- name: Materialize WPF reference assemblies (WPF profile)
3534
run: |
36-
root="${DOTNET_ROOT:-/usr/share/dotnet}"
37-
echo "DOTNET_ROOT=$root"
38-
echo "::group::Already in the SDK packs?"
39-
find "$root/packs" -ipath '*WindowsDesktop.App.Ref*' -name 'PresentationFramework.dll' 2>/dev/null | head || echo "(none in SDK packs)"
40-
echo "::endgroup::"
41-
echo "::group::Restore a net8.0-windows/UseWPF stub (EnableWindowsTargeting)"
35+
# The WindowsDesktop ref pack isn't in the Linux SDK, but a net8.0-windows
36+
# /UseWPF stub restores it cross-platform (EnableWindowsTargeting). Export
37+
# the ref dir so the extractor (OWN_EXTRA_REF_DIRS) can resolve WPF events
38+
# and timers instead of dropping them as OWN050.
4239
tmp=$(mktemp -d)
4340
printf '%s\n' \
4441
'<Project Sdk="Microsoft.NET.Sdk">' \
@@ -47,18 +44,15 @@ jobs:
4744
' <UseWPF>true</UseWPF>' \
4845
' <EnableWindowsTargeting>true</EnableWindowsTargeting>' \
4946
' </PropertyGroup>' \
50-
'</Project>' > "$tmp/probe.csproj"
51-
dotnet restore "$tmp/probe.csproj" 2>&1 | tail -8 || echo "RESTORE FAILED"
52-
echo "::endgroup::"
53-
echo "::group::Where did the WPF ref assemblies land?"
54-
d=$(find "$root/packs/Microsoft.WindowsDesktop.App.Ref" -type d -name 'net8.0' 2>/dev/null | head -1)
55-
[ -z "$d" ] && d=$(find "$HOME/.nuget/packages/microsoft.windowsdesktop.app.ref" -type d -name 'net8.0' 2>/dev/null | head -1)
56-
echo "WPF ref dir: ${d:-NONE FOUND}"
47+
'</Project>' > "$tmp/wpfref.csproj"
48+
dotnet restore "$tmp/wpfref.csproj" >/dev/null 2>&1 || echo "wpf-ref restore failed (continuing without)"
49+
d=$(find "$HOME/.nuget/packages/microsoft.windowsdesktop.app.ref" -type d -name 'net8.0' 2>/dev/null | sort | tail -1)
5750
if [ -n "$d" ]; then
58-
echo "count of ref dlls: $(find "$d" -name '*.dll' | wc -l)"
59-
ls "$d" | grep -iE 'Presentation|WindowsBase|System.Xaml|System.Windows' | head -20
51+
echo "OWN_EXTRA_REF_DIRS=$d" >> "$GITHUB_ENV"
52+
echo "WPF refs ready: $d ($(find "$d" -name '*.dll' | wc -l) dlls)"
53+
else
54+
echo "WPF refs NOT found — the mine will run without them (OWN050 on framework types)"
6055
fi
61-
echo "::endgroup::"
6256
- name: Read & validate the target
6357
id: target
6458
run: |

‎corpus/mine-target.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
# First non-comment line: a GitHub "owner/repo" or an https git URL. One repo/run.
33
# Optional lines: ref=<branch|tag|sha>, paths=<subdir of the target to scan>.
44
# Bump this file (commit + push) to kick off a mine; read the result in the run log.
5+
# cycle: re-mine WITH the WPF reference pack loaded (OWN_EXTRA_REF_DIRS).
56
NickeManarin/ScreenToGif

‎frontend/roslyn/OwnSharp.Extractor/Program.cs‎

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,11 +415,28 @@ t is "IDisposable" or "IAsyncDisposable" or "CancellationTokenSource"
415415
// in-project types and BCL events; external types (WPF/DevExpress) stay
416416
// unresolved and are surfaced as OWN050 "unchecked", never guessed as leaks.
417417
// Error-tolerant: compile diagnostics are irrelevant — we only read symbols.
418-
var references = ((AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES") as string) ?? "")
418+
var tpa = ((AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES") as string) ?? "")
419419
.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries)
420420
.Where(p => p.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
421-
.Select(p => (MetadataReference)MetadataReference.CreateFromFile(p))
422421
.ToList();
422+
var refNames = new HashSet<string>(tpa.Select(Path.GetFileName), StringComparer.OrdinalIgnoreCase);
423+
var references = tpa.Select(p => (MetadataReference)MetadataReference.CreateFromFile(p)).ToList();
424+
// P-004 WPF profile: widen the reference set with assemblies named by the
425+
// OWN_EXTRA_REF_DIRS env var (colon-separated dirs) — e.g. the WindowsDesktop ref
426+
// pack — so framework events/timers (Button.Click, DispatcherTimer.Tick) resolve to
427+
// real symbols instead of surfacing as OWN050 on a WPF app. Additive and best-
428+
// effort: unset => unchanged behaviour; a DLL whose simple name a TPA reference
429+
// already provides is skipped so System.* is not double-referenced from two packs.
430+
foreach (var dir in (Environment.GetEnvironmentVariable("OWN_EXTRA_REF_DIRS") ?? "")
431+
.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries))
432+
{
433+
if (!Directory.Exists(dir)) continue;
434+
var added = 0;
435+
foreach (var dll in Directory.EnumerateFiles(dir, "*.dll"))
436+
if (refNames.Add(Path.GetFileName(dll)))
437+
{ references.Add(MetadataReference.CreateFromFile(dll)); added++; }
438+
Console.Error.WriteLine($"extractor: +{added} extra references from {dir}");
439+
}
423440
var compilation = CSharpCompilation.Create(
424441
"own", parsed.Select(p => p.tree), references,
425442
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

0 commit comments

Comments
 (0)