Skip to content

Commit 341f948

Browse files
author
Copilot CI
committed
Name the type that actually owns the member a build break rejected
build-failed is the largest attempt kind in the pipeline at 234 of 1311 attempts, and in 34 of 65 build-failed runs the identical file+error recurs across attempts - the agent re-submits the same mistake. Restricting the corpus to lines that really say ": error " (rather than counting occurrences of a code, which puts MAUI's own MSB4011 and NETSDK1206 build warnings on top) leaves 449 real errors, led by CS1061, CS0103 and CS0117. The recurring ones are all the same mistake: a real API reached for under a wrong name - SafeAreaEdges.Container, SafeAreaEdges.SoftInput, Size.Request, Shell.TitleColor. Get-ReplicationMissingIdentifierEvidence extracted only the member from "'SafeAreaEdges' does not contain a definition for 'Container'" and searched for it. 'Container' is a whole word in 151 C# files under src/, so reporting two of them spends the agent's attention to say nothing. The diagnostic names the type too, and that was the half being discarded. For CS0117 and CS1061 it now asks which type actually exposes the member, ranks by frequency and excludes the type that just rejected it - answering "use SafeAreaEdges.SoftInput" to "SafeAreaEdges does not contain SoftInput" is the one reply guaranteed to be wrong, and that string does occur in source. Verified against the four real corpus failures: Container and SoftInput both resolve to SafeAreaRegions, Request to SizeRequest, all as the top hit; an invented member yields no owner line and falls through to the existing "appears in no C# source file" answer. Suite 1892/0.
1 parent 4ddf219 commit 341f948

2 files changed

Lines changed: 102 additions & 3 deletions

File tree

.github/scripts/Replicate-Issue.Tests.ps1

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11622,6 +11622,53 @@ Describe 'An invented API is named as invented' {
1162211622
$evidence | Should -Match 'do not use it again'
1162311623
}
1162411624

11625+
It 'names the type that really owns the member' {
11626+
# Measured: the bare member behind "'SafeAreaEdges' does not contain a
11627+
# definition for 'Container'" matches 151 C# files, so reporting two of
11628+
# them is noise. SafeAreaRegions.Container is the answer, and it is the
11629+
# top hit by a wide margin. Run 15092216-class build breaks repeated the
11630+
# identical diagnostic across attempts; 34 of 65 build-failed runs did.
11631+
$evidence = Get-ReplicationMissingIdentifierEvidence `
11632+
-Diagnostics ("error CS0117: 'SafeAreaEdges' does not contain a " +
11633+
"definition for 'Container'") `
11634+
-RepositoryRoot $script:apiRepoRoot
11635+
$evidence | Should -Match "'Container' is not a member of 'SafeAreaEdges'"
11636+
$evidence | Should -Match 'SafeAreaRegions'
11637+
}
11638+
11639+
It 'ranks the owner that is actually used most first' {
11640+
$evidence = Get-ReplicationMissingIdentifierEvidence `
11641+
-Diagnostics "error CS1061: 'Size' does not contain a definition for 'Request'" `
11642+
-RepositoryRoot $script:apiRepoRoot
11643+
$owners = [regex]::Match($evidence, "'Request' is used on (?<list>[^.]+)\.")
11644+
$owners.Success | Should -BeTrue
11645+
$owners.Groups['list'].Value | Should -Match '^SizeRequest'
11646+
}
11647+
11648+
It 'never suggests the type that just rejected the member' {
11649+
# Answering "use SafeAreaEdges.SoftInput" to "SafeAreaEdges does not
11650+
# contain SoftInput" is the one reply guaranteed to be wrong, and the
11651+
# name does occur on that type in source.
11652+
$evidence = Get-ReplicationMissingIdentifierEvidence `
11653+
-Diagnostics ("error CS1061: 'SafeAreaEdges' does not contain a " +
11654+
"definition for 'SoftInput'") `
11655+
-RepositoryRoot $script:apiRepoRoot
11656+
$owners = [regex]::Match($evidence, "'SoftInput' is used on (?<list>[^.]+)\.")
11657+
$owners.Success | Should -BeTrue
11658+
$owners.Groups['list'].Value | Should -Not -Match 'SafeAreaEdges'
11659+
}
11660+
11661+
It 'claims no owner for a member that exists nowhere' {
11662+
# Silence is the honest answer here, and the generic search still says
11663+
# the name is absent.
11664+
$evidence = Get-ReplicationMissingIdentifierEvidence `
11665+
-Diagnostics ("error CS1061: 'Picker' does not contain a definition " +
11666+
"for 'TotallyMadeUpZZZ'") `
11667+
-RepositoryRoot $script:apiRepoRoot
11668+
$evidence | Should -Not -Match 'is used on'
11669+
$evidence | Should -Match 'appears in no C# source file under src/'
11670+
}
11671+
1162511672
It 'points at the file when the identifier is real' {
1162611673
# ItemsSource is a real MAUI member, so the honest answer is where to
1162711674
# read it, not that it is absent.

.github/scripts/Replicate-Issue.ps1

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,56 @@ function Get-ReplicationMissingIdentifierEvidence {
11151115
return ''
11161116
}
11171117

1118+
# CS0117 and CS1061 name *both* the type and the member, and the member
1119+
# alone is the less useful half. Measured on the cached corpus, searching
1120+
# for the bare member behind "'SafeAreaEdges' does not contain a definition
1121+
# for 'Container'" matches 151 C# files and reports two of them, which is
1122+
# noise. Asking instead which type actually exposes that member answers it
1123+
# outright: SafeAreaRegions.Container, 21 uses, top hit. The same lookup
1124+
# resolves SoftInput to SafeAreaRegions and Request to SizeRequest - in
1125+
# each case the author had reached for a property name or a Xamarin.Forms
1126+
# type as though it were the enum.
1127+
$ownerLines = [Collections.Generic.List[string]]::new()
1128+
$ownerPattern = "'(?<type>[A-Za-z_][A-Za-z0-9_]*)' does not contain a definition for " +
1129+
"'(?<name>[A-Za-z_][A-Za-z0-9_]*)'"
1130+
$seenMembers = [Collections.Generic.HashSet[string]]::new()
1131+
foreach ($match in [regex]::Matches($Diagnostics, $ownerPattern)) {
1132+
if ($ownerLines.Count -ge $MaximumIdentifiers) { break }
1133+
$wrongType = $match.Groups['type'].Value
1134+
$member = $match.Groups['name'].Value
1135+
if (-not $seenMembers.Add($member)) { continue }
1136+
1137+
$owners = @()
1138+
try {
1139+
# -I skips binary files: the aotprofile blobs otherwise contribute a
1140+
# "Binary file ... matches" line that would be reported as a type.
1141+
$uses = & git -C $RepositoryRoot grep -hoPI `
1142+
"(?<![A-Za-z0-9_])[A-Z][A-Za-z0-9_]*\.$member(?![A-Za-z0-9_])" `
1143+
-- 'src/Controls/src' 'src/Core/src' 2>$null
1144+
$owners = @($uses |
1145+
ForEach-Object { ($_ -split '\.')[0] } |
1146+
Where-Object { $_ -and $_ -ne $wrongType } |
1147+
Group-Object |
1148+
Sort-Object -Property @{ Expression = { $_.Count } ; Descending = $true }, Name |
1149+
Select-Object -First 2)
1150+
} catch {
1151+
# A search that could not run says nothing, and inventing an owner
1152+
# here would be the confident wrong answer this phase exists to stop.
1153+
continue
1154+
}
1155+
1156+
if ($owners.Count -gt 0) {
1157+
$described = @($owners | ForEach-Object {
1158+
$unit = if ($_.Count -eq 1) { 'use' } else { 'uses' }
1159+
"$($_.Name) ($($_.Count) $unit)"
1160+
}) -join ', '
1161+
$ownerLines.Add(
1162+
"'$member' is not a member of '$wrongType'. In this repository " +
1163+
"'$member' is used on $described. Read that declaration and use " +
1164+
"the type that really owns the member instead of renaming it.") | Out-Null
1165+
}
1166+
}
1167+
11181168
$names = [Collections.Generic.List[string]]::new()
11191169
foreach ($pattern in @(
11201170
"does not contain a definition for '(?<name>[A-Za-z_][A-Za-z0-9_]*)'",
@@ -1127,7 +1177,7 @@ function Get-ReplicationMissingIdentifierEvidence {
11271177
}
11281178
}
11291179
}
1130-
if ($names.Count -eq 0) {
1180+
if ($names.Count -eq 0 -and $ownerLines.Count -eq 0) {
11311181
return ''
11321182
}
11331183

@@ -1161,11 +1211,13 @@ function Get-ReplicationMissingIdentifierEvidence {
11611211
}
11621212
}
11631213

1164-
if ($lines.Count -eq 0) {
1214+
if ($lines.Count -eq 0 -and $ownerLines.Count -eq 0) {
11651215
return ''
11661216
}
11671217

1168-
return ($lines -join ' ')
1218+
# The owner evidence goes first: it names the type to use, where the
1219+
# generic search only says whether a name exists somewhere.
1220+
return ((@($ownerLines) + @($lines)) -join ' ')
11691221
}
11701222

11711223
function Get-ReplicationCompilerDiagnostics {

0 commit comments

Comments
 (0)