Problem
Every C# detector and rewriter in studioctl-server's v8Tov9 upgrade works on the syntax tree only — no Compilation, no semantic model. Matching on unqualified names forces heuristics that both over-report and under-report:
ServiceTaskResultApiDetector cannot match a bare Failed(...) because the name is too generic, so it only matches receiver-qualified call sites and silently misses aliased, using static and fully qualified spellings — while flagging an app's own type that happens to share an SDK type's name.
LegacyEFormidlingCodeDetector disambiguates removed overloads by counting arguments.
CorrespondenceApiMigration cannot complete a rewrite it would otherwise do: a WithData argument whose type cannot be determined from syntax is reported for the developer to finish by hand rather than rewritten. That is a user-facing gap, not just internal tidiness.
Proposal
Restore and compile the app against its v8 packages before bumping the csproj, and run detection against that compilation. The ordering matters: the symbols the detectors hunt are precisely the ones v9 removes, so only the v8 dependency graph resolves them — a post-bump compilation resolves them to error symbols and buys little.
Requirements:
- Fallback is a first-class outcome. When the app cannot be compiled — it does not build before the upgrade either, the SDK/targeting pack it targets is not installed, or the machine is offline — detection runs syntax-only exactly as today, with the reason stated, and the upgrade proceeds. It never fails because of the compile step.
- Cost is measured, not assumed, and the compile duration is printed on every run.
- Rewriters and detectors share one source view so a usage is either fixed by a rewriter or reported by a detector, never both — and semantic detection must bind against the pre-rewrite state, since rewrites move code toward v9 where the v8 compilation can no longer bind the removed names.
Deliberately out of scope
Implementation: #19934.
Problem
Every C# detector and rewriter in
studioctl-server'sv8Tov9upgrade works on the syntax tree only — noCompilation, no semantic model. Matching on unqualified names forces heuristics that both over-report and under-report:ServiceTaskResultApiDetectorcannot match a bareFailed(...)because the name is too generic, so it only matches receiver-qualified call sites and silently misses aliased,using staticand fully qualified spellings — while flagging an app's own type that happens to share an SDK type's name.LegacyEFormidlingCodeDetectordisambiguates removed overloads by counting arguments.CorrespondenceApiMigrationcannot complete a rewrite it would otherwise do: aWithDataargument whose type cannot be determined from syntax is reported for the developer to finish by hand rather than rewritten. That is a user-facing gap, not just internal tidiness.Proposal
Restore and compile the app against its v8 packages before bumping the csproj, and run detection against that compilation. The ordering matters: the symbols the detectors hunt are precisely the ones v9 removes, so only the v8 dependency graph resolves them — a post-bump compilation resolves them to error symbols and buys little.
Requirements:
Deliberately out of scope
ExternalMaskinportenPackageDetector,MaskinportenClientOverrideDetector) stay syntax-only: One Maskinporten identity per app: bind provisioned credentials outside the config root, remove the public configuration surface #20048 retires the v9 invariants they describe, so their guidance is due for a rewrite when that lands, and semantic precision now would be churn.Implementation: #19934.