razor
razor copied to clipboard
Syntax of the whole document collapses when attribute value can't be assigned to type
VS 17.10.0 P1
I mistakenly used component attribute Icon
(which type is Type
) instead of Value
(which type is Icon
, the right one in this context):
https://github.com/dotnet/razor/assets/9047283/6105ebb3-a0f8-4482-9591-2df43da7691e
Instead of showing an error that Icon
can't be assigned to Type
, the whole syntax of the file collapses beginning from an earlier point. I get like ~80 false errors for a 250 lines file, which is then a nightmare to debug, what is the real problem.
Also note how broken code completion still is.
This ends up generating typeof(Icon.FromImageUrl(icon))
, which the C# parser chokes on. The actual errors depend a lot on the exact structure of the code. eg, see the errors on line 10 vs 20, or even just trying it in a plain C# file.
Thanks for the explanation. I knew that Razor treats string
typed properties differently, which is comfy, but I didn't know that it distinguishes Type
typed properties, too (properties, not generic type arguments).
My assumption as a user was that since that component parameter holds a Type
as runtime data:
[Parameter]
public Type Icon { get; set; }
It is treated as any other type (except string), and the argument is passes as a value/data:
component.Icon = type;
But what you suggest is that the compiler generates this:
component.Icon = typeof(VALUE);
If this is the case:
- Although the generic type arguments are handled properly, have their own syntax, I may be not aware yet about what is the use case when it is useful to spare a
typeof()
expression? Because it could work like this:Icon="typeof(...)"
- How can I pass a
Type
typed value at runtime instead of a type name at compile time? - Or was it not considered when the specification was designed and now it would be a breaking change to fix/diverge?
But what you suggest is that the compiler generates this:
That's not correct. The Icon
is not a parameter like [Parameter] public Type Icon { get; set; }
(if it were, you would have to use typeof
explicitly), it's a type parameter of the generic component like class FluentIcon<Icon> : ComponentBase
(source) - there you cannot pass any dynamic types. Note that the typeof
is generated only for design-time IDE purposes, for runtime compilation the type you write is used directly.
The Icon is not a parameter like [Parameter] public Type Icon { get; set; } (if it were, you would have to use typeof explicitly), it's a type argument of the generic component like class FluentIcon<Icon> : ComponentBase (source)
Oh yes, you are correct, it is a type parameter! Thank you.
There was a couple of things which made me falsely believe that it was property:
- there was no conventional T prefix (belongs to
fluentui-blazor
) - the dicussion about generating a
typeof()
expression - when I wanted to check
Go To Definition
did not work at that time for some reason - Quick Info was a little confusing (although the description states correctly it is a type parameter), because it shows it like a
Type
-typed property, in a declaration formatType .Icon
, with the icon of the property (instead of the icon of type parameters) - also, the diagnostic
RZ2008
refers to it likeattributes of type System.Type
Note that the typeof is generated only for design-time IDE purposes, for runtime compilation the type you write is used directly.
Thanks for the clarification, now I get it.
Although none of these exempts me for not checking the source or reading the quick info carefully :D, I could still see some room for improvement here:
- clarification of quick info icons, messages and diagnostics (although it is debatable that in Razor markup type arguments are passed as "component attributes"?), in my opinion, it would be clearer to:
- use the type parameter icon (like in C#)
- the declaration should show it as a type parameter, not as a property (like in C#)
- do not refer to it as
System.Type
- whatever it compiles to, the diagnostics should be shown at the right places
- if it is empty
- if it is not a type
- if it is the wrong type, etc.
- even if I leave a simple data property (this time really :)) empty:
- sometimes I can't navigate to the source from Razor, although I can't reproduce that now with a freshly opened VS
Thanks!