✅ Roslyn analyzer: System.Guid only has _dummyPrimitive field?
I'm currently writing an analyzer that inspects the fields of certain types. One of the tests failed because it analyzed
System.Guid
and I noticed that, according to this query:
System.Guid
only has a single field: int _dummyPrimitive
. I know that guids are larger than 4 bytes and given the field name, I assume this is a placeholder of some sort. I could just ignore System.Guid
but I suspect this is not the only type that behaves this way.
1. Why is the ITypeSymbol
of System.Guid
a placeholder (or whatever this is) and not the original definition?
2. Can I somehow detect when a type is a placeholder?11 Replies
First, #roslyn is a channel you might want to get familiar with
Second, analyzing types from other assemblies is not a good idea, because other assemblies are very likely to be ref assemblies
Reference assemblies
Learn about reference assemblies, a special type of assemblies in .NET that contain only the library's public API surface
You can't really detect such assemblies in any systematic fashion, roslyn neither knows nor cares whether a reference is a real assembly or a ref assembly
What are you actually trying to do with this analyzer?
I see, can project references also resolve to reference assemblies?
We do quite extensive native interop between C# and C++ and I'm writing an analyzer that ensures we follow some internal guidelines when marshaling data. The analyzer effectively looks at all
static extern
methods and analyzes their parameters and return types.
One part of the analyzer looks at the fields of a type to check if it's a wrapper of a primitive, e.g. struct Bool { byte b; }
. That's where I ran into the Guid
issue.Not usually
This strikes me as something that should end going through something with an
unmanaged
constraint?I have an analyzer for more complex types that checks for
unmanaged
(in generics, for example). This specific analyzer is there to flag parameters that are expected to be passed as a pointer. Basically, everything that doesn't fit in a register should be passed as a pointer in some form (e.g. in Guid param1
). Since the unmanaged
constraint is valid on larger types, I cannot use it here. I'm also aware that doesn't fit in a register is very hard to determine because of the marshaler, so I'm overly pessimistic in the analyzer (which is fine in our scenario).Yeah, that's unfortunately going to be basically impossible to determine unless you never use reference assemblies (which slows down the build and increases memory usage)
You may have to go extremely pessimistic and have some hard-coded list of types that are acceptable by value
That was my idea as well. It shouldn't be too bad, since we don't use many types outside of our own namespace for marshaling. It's mainly primitives and two or three others like
Guid
.
Thanks a lot for the help!Yw. Make sure to $close the thread
Use the
/close
command to mark a forum thread as answeredWill, do. I had issues last time where it didn't let me close the thread. Lets see if I'm mighty enough this time.