Context
Razor components support opt-in compile-time ~/ asset-path expansion (dotnet/aspnetcore#68229): a literal like <img src="~/images/logo.png"> is rewritten to Assets["images/logo.png"] when the (element, attribute) pair is declared via [AcceptsAssetPath] or a component parameter is marked [AssetPath]. The compiler side lives under src/Razor/src/Compiler (ComponentTildePathPass, AcceptsAssetPathTagHelperProducer, PropertyMetadata.AcceptsAssetPath).
Today there is no IntelliSense for these paths. Inside an opted-in attribute value, ~/... is plain HTML attribute text to the tooling; nothing offers the set of available static web assets as completions.
Proposal
Provide completion for asset paths when the cursor is inside an opted-in location whose value begins with ~/, offering the project's available static web assets.
This splits into two halves:
1. Where to offer it (trigger) -- small, idiomatic
Razor tooling aggregates IRazorCompletionItemProvider implementations via RazorCompletionListProvider (e.g. DirectiveAttributeCompletionItemProvider). A new provider can reuse the exact opt-in metadata the compiler already reads:
- the
[AcceptsAssetPath] allowlist, surfaced as AssetPathMetadata tag-helper descriptors, and
[AssetPath] component parameters, surfaced as PropertyMetadata.AcceptsAssetPath.
Using that, the provider detects the cursor is inside an opted-in element/attribute or component parameter whose value starts with ~/ and contributes completion items. Under cohosting this lands in the cohost completion path (CohostDocumentCompletionEndpoint).
2. What to offer (the data) -- the real work
The available assets come from the static web assets manifest the SDK emits. Razor tooling currently has zero awareness of it (no manifest reading anywhere under src/Razor). This requires plumbing the project's static-web-asset keys into the language server -- an OOP/cohost service that reads the manifest and refreshes it on rebuild.
Effort / open questions
- The completion provider itself is small (~a day).
- The asset-source plumbing + freshness across rebuilds is the bulk of the work and the main open question (manifest location/format, how to keep it current, OOP surface).
Links
Context
Razor components support opt-in compile-time
~/asset-path expansion (dotnet/aspnetcore#68229): a literal like<img src="~/images/logo.png">is rewritten toAssets["images/logo.png"]when the(element, attribute)pair is declared via[AcceptsAssetPath]or a component parameter is marked[AssetPath]. The compiler side lives undersrc/Razor/src/Compiler(ComponentTildePathPass,AcceptsAssetPathTagHelperProducer,PropertyMetadata.AcceptsAssetPath).Today there is no IntelliSense for these paths. Inside an opted-in attribute value,
~/...is plain HTML attribute text to the tooling; nothing offers the set of available static web assets as completions.Proposal
Provide completion for asset paths when the cursor is inside an opted-in location whose value begins with
~/, offering the project's available static web assets.This splits into two halves:
1. Where to offer it (trigger) -- small, idiomatic
Razor tooling aggregates
IRazorCompletionItemProviderimplementations viaRazorCompletionListProvider(e.g.DirectiveAttributeCompletionItemProvider). A new provider can reuse the exact opt-in metadata the compiler already reads:[AcceptsAssetPath]allowlist, surfaced asAssetPathMetadatatag-helper descriptors, and[AssetPath]component parameters, surfaced asPropertyMetadata.AcceptsAssetPath.Using that, the provider detects the cursor is inside an opted-in element/attribute or component parameter whose value starts with
~/and contributes completion items. Under cohosting this lands in the cohost completion path (CohostDocumentCompletionEndpoint).2. What to offer (the data) -- the real work
The available assets come from the static web assets manifest the SDK emits. Razor tooling currently has zero awareness of it (no manifest reading anywhere under
src/Razor). This requires plumbing the project's static-web-asset keys into the language server -- an OOP/cohost service that reads the manifest and refreshes it on rebuild.Effort / open questions
Links
ComponentTildePathPass/AcceptsAssetPathTagHelperProducerundersrc/Razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler