Skip to content

[Feature]: Explain and allow overriding XAML project ownership when resolution fails #217

Description

Is your feature request related to a problem? Please describe.

XamlProjectResolver.FindOwningProject (server/src/WinUiXaml.Workspace/XamlProjectResolver.cs) walks upward from a XAML file looking for a directory containing exactly one .csproj. It returns a bare null in several distinct situations:

  • the directory contains two or more .csproj files (ambiguous — the walk aborts immediately, it does not continue to an unambiguous ancestor, lines 68-71)
  • no .csproj is found anywhere up to the boundary — e.g. XAML linked in from a shared folder that lives outside any project
  • the document falls outside every allowedRoot

All of these collapse into the same null. ResolveAsync and ResolveFrameworkAsync both just return null, so the document is served project-less: the tolerant parser, syntax diagnostics and TextMate coloring still work, but there is no compilation — no type-aware completion, no x:Bind resolution, no hover types, no F12 into code-behind.

The user gets no indication of why, and no way to correct it. FindOwningProjectTests.MultipleProjectsInDirectory_ReturnsNullWhenAmbiguous and NoProject_ReturnsNull assert the identical observable outcome, which confirms the two states are indistinguishable to callers.

There is currently no setting anywhere in the extension or server for pinning a project.

Describe the solution you'd like

Two changes, neither of which requires MSBuild evaluation:

1. Distinguish the failure reason. Return a reason alongside the result (or add TryFindOwningProject(out var reason)) covering at least Found, Ambiguous, NoProjectFound, and OutsideAllowedRoot. Surface it in the server log and in whatever project-status affordance the client presents, so an ambiguous directory reads as "two projects here, pick one" rather than silence.

2. Let the user pin a project. A workspace-folder-scoped setting (e.g. winui-xaml.projectPath) and/or a WinUI: Select XAML Project quick-pick. This one mechanism addresses ambiguity, linked/shared XAML, and unusual layouts together — which matters, because ambiguity is likely the least common cause of a null resolution.

Optional third step — a default instead of giving up. When candidates are ambiguous, prefer the one whose TargetFramework matches net*-windows10.0.* (the WinUI head, almost certainly the one whose IntelliSense is wanted), falling back to alphabetical order. TargetFramework is normally a literal property, so this is an XML read rather than a design-time build.

Additional context

Why content-based disambiguation is not the answer. The instinct is to ask which candidate actually includes the XAML as a Page/ApplicationDefinition item. But in the realistic ambiguous scenario — two heads over one shared source tree — both are SDK-style projects whose default globs pick up **/*.xaml, so both genuinely include the file. There is no owner to discover, only a preference to record. Content-based disambiguation would cost an MSBuild evaluation per candidate and frequently return "both."

Likelihood. Multiple .csproj in one folder is uncommon for WinUI: no WinUI template produces it, and the usual app + Windows Application Packaging Project layout is App.csproj + App.wapproj, which is unaffected because the glob is *.csproj only. It shows up mainly in UWP → WinUI 3 side-by-side migrations. This is a judgment call, not a telemetry-backed measurement.

Related invalidation gap (needs verification before acting). FindOwningProject is also used for cache invalidation at server/src/WinUiXaml.LanguageServer/XamlLanguageServer.cs:558, guarded by if (owning != null). A .cs edit inside a multi-project directory therefore invalidates nothing. That is harmless for a project that was never loaded, but if such a project is a ProjectReference of a loaded app project, edits to its sources may not invalidate the app's cached workspace. There is no test covering this path, and Invalidate does have a ContainsProject check for referenced projects that should be traced before treating it as a bug. Adding an ambiguity tie-break would incidentally close this gap for those directories.

Found while reviewing the XAML language service integration in #50.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions