Reputation: 143
Using Roslyn, how to determine whether an ITypeSymbol
is a primitive type or not?
The ITypeSymbol
does not have the IsPrimitive
property like Type.IsPrimitive
Is there a way to convert ITypeSymbol
to Type or some other way to determine whether an ITypeSymbol
is a primitive type?
Upvotes: 5
Views: 2456
Reputation: 367
Looks like the code to determine that is in the TypedConstant class, but it is internal and I couldn't find a public API that would nicely get me there. I ended up copying the method into to my project.
/// <remarks>
/// TypedConstant isn't computing its own kind from the type symbol because it doesn't
/// have a way to recognize the well-known type System.Type.
/// </remarks>
internal static TypedConstantKind GetTypedConstantKind(ITypeSymbol type, Compilation compilation)
{
Debug.Assert(type != null);
switch (type.SpecialType)
{
case SpecialType.System_Boolean:
case SpecialType.System_SByte:
case SpecialType.System_Int16:
case SpecialType.System_Int32:
case SpecialType.System_Int64:
case SpecialType.System_Byte:
case SpecialType.System_UInt16:
case SpecialType.System_UInt32:
case SpecialType.System_UInt64:
case SpecialType.System_Single:
case SpecialType.System_Double:
case SpecialType.System_Char:
case SpecialType.System_String:
case SpecialType.System_Object:
return TypedConstantKind.Primitive;
default:
switch (type.TypeKind)
{
case TypeKind.Array:
return TypedConstantKind.Array;
case TypeKind.Enum:
return TypedConstantKind.Enum;
case TypeKind.Error:
return TypedConstantKind.Error;
}
if (compilation != null &&
compilation.IsSystemTypeReference(type))
{
return TypedConstantKind.Type;
}
return TypedConstantKind.Error;
}
}
Upvotes: 4
Reputation: 9
Try the following extension methods:
//eg: symbol.IsFullNameEquals("List`1", "Generic", "Collections", "System")
internal static bool IsFullNameEquals(this ISymbol symbol, params string[] nameParts) {
if (symbol == null) throw new ArgumentNullException("symbol");
if (nameParts == null || nameParts.Length == 0) throw new ArgumentNullException("nameParts");
var idx = 0;
for (; symbol != null; symbol = symbol.ContainingSymbol) {
var name = symbol.MetadataName;
if (string.IsNullOrEmpty(name)) break;
if (idx == nameParts.Length) return false;
if (name != nameParts[idx]) return false;
idx++;
}
return idx == nameParts.Length;
}
//eg: var idx = symbol.MatchFullName(new []{"List`1", "Dictionary`2"}, new []{"Generic", "Collections", "System"});
//return value: -1: none; 0: symbol is List`1; 1: symbol is Dictionary`2
internal static int MatchFullName(this ISymbol symbol, string[] typeNames, string[] outerNameParts) {
if (symbol == null) throw new ArgumentNullException("symbol");
if (typeNames == null || typeNames.Length == 0) throw new ArgumentNullException("typeNames");
var fullLength = 1 + (outerNameParts != null ? outerNameParts.Length : 0);
int idx = 0, result = -1;
for (; symbol != null; symbol = symbol.ContainingSymbol) {
var name = symbol.MetadataName;
if (string.IsNullOrEmpty(name)) break;
if (idx == fullLength) return -1;
if (idx == 0) {
for (var i = 0; i < typeNames.Length; i++) {
if (name == typeNames[i]) {
result = i;
break;
}
}
if (result == -1) return -1;
}
else {
if (name != outerNameParts[idx - 1]) return -1;
}
idx++;
}
if (idx == fullLength) return result;
return -1;
}
Upvotes: 0
Reputation: 3293
Whether a type is primitive or not depends on your language. In C# DateTime is not a primitive, but it is in VB. Since ITypeSymbol is used for both languages, it does not have language-specific properties.
Upvotes: 1