Summary
The current #496 / #782 suffix-guard fix in SymbolExtractor still drops real C# method declarations when the return type is a legal contextual-keyword type name such as await or yield.
Roslyn accepts these declarations (with warning CS8981 only), but cdidx drops the methods entirely from symbols, definition, and outline.
Repro
CDIDX='dotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dll'
TMPDIR=$(mktemp -d /tmp/cdidx-cs-contextual-return.XXXXXX)
cat > "$TMPDIR/Class1.cs" <<'EOF'
namespace Demo;
public class await {}
public class yield {}
public class Uses
{
public await MakeAwait() => new await();
public yield MakeYield() => new yield();
}
EOF
# Control: Roslyn accepts the code.
(
cd "$TMPDIR"
dotnet new classlib --framework net8.0 >/dev/null
dotnet build -nologo
)
"$CDIDX" index "$TMPDIR" --json >/dev/null
"$CDIDX" outline Class1.cs --db "$TMPDIR/.cdidx/codeindex.db" --json
Observed outline payload (abridged):
{
"symbols": [
{"kind":"namespace","name":"Demo"},
{"kind":"class","name":"await"},
{"kind":"class","name":"yield"},
{"kind":"class","name":"Uses"}
]
}
Missing:
{"kind":"function","name":"MakeAwait","return_type":"await",...}
{"kind":"function","name":"MakeYield","return_type":"yield",...}
Root cause
HasInvalidCSharpReturnTypeSuffix(...) rejects any captured return-type tail whose final token is one of:
as
is
await
return
throw
yield
new
That is correct for phantom call-site fragments like elapsed < TimeSpan.FromSeconds(...), but it is too broad for legal contextual-keyword identifiers used as type names. Unlike new, await and yield do not need @ here; Roslyn accepts them as identifiers.
The current #782 follow-up only exempted verbatim identifiers such as @new, so the non-verbatim contextual-keyword case is still broken.
Suggested direction
Make the suffix guard distinguish between:
- real declaration return types whose final token is a contextual-keyword identifier (
await, yield, possibly other legal contextual identifiers)
- operator / statement fragments from call-site false positives
A few possible directions:
- shrink the deny-list to truly impossible declaration tails and rely on the surrounding regex / declaration context for the rest
- keep the deny-list but exempt contextual-keyword identifiers that Roslyn accepts as type names
- move the guard closer to the specific phantom-call-site pattern(s) that motivated
#496, instead of applying it to every C# row with ReturnTypeGroup
Tests to add
Please add focused regressions in tests/CodeIndex.Tests/SymbolExtractorTests.cs for at least:
public class await {}
public class yield {}
public class Uses
{
public await MakeAwait() => new await();
public yield MakeYield() => new yield();
}
Assert that:
class await and class yield are present
function MakeAwait and function MakeYield are present
- their
ReturnType values are await / yield
Environment
- Reproduced on macOS arm64
- Binary: local build from current branch
fix-issue496-782 via dotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dll
- Discovered during adversarial review of
origin/main..HEAD
Summary
The current
#496/#782suffix-guard fix inSymbolExtractorstill drops real C# method declarations when the return type is a legal contextual-keyword type name such asawaitoryield.Roslyn accepts these declarations (with warning
CS8981only), butcdidxdrops the methods entirely fromsymbols,definition, andoutline.Repro
Observed outline payload (abridged):
{ "symbols": [ {"kind":"namespace","name":"Demo"}, {"kind":"class","name":"await"}, {"kind":"class","name":"yield"}, {"kind":"class","name":"Uses"} ] }Missing:
{"kind":"function","name":"MakeAwait","return_type":"await",...} {"kind":"function","name":"MakeYield","return_type":"yield",...}Root cause
HasInvalidCSharpReturnTypeSuffix(...)rejects any captured return-type tail whose final token is one of:asisawaitreturnthrowyieldnewThat is correct for phantom call-site fragments like
elapsed < TimeSpan.FromSeconds(...), but it is too broad for legal contextual-keyword identifiers used as type names. Unlikenew,awaitandyielddo not need@here; Roslyn accepts them as identifiers.The current
#782follow-up only exempted verbatim identifiers such as@new, so the non-verbatim contextual-keyword case is still broken.Suggested direction
Make the suffix guard distinguish between:
await,yield, possibly other legal contextual identifiers)A few possible directions:
#496, instead of applying it to every C# row withReturnTypeGroupTests to add
Please add focused regressions in
tests/CodeIndex.Tests/SymbolExtractorTests.csfor at least:Assert that:
class awaitandclass yieldare presentfunction MakeAwaitandfunction MakeYieldare presentReturnTypevalues areawait/yieldEnvironment
fix-issue496-782viadotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dllorigin/main..HEAD