|
|
@ -37,14 +37,19 @@ namespace ICSharpCode.Decompiler.TypeSystem |
|
|
|
SRM.CustomAttributeHandleCollection? attributes, |
|
|
|
SRM.CustomAttributeHandleCollection? attributes, |
|
|
|
SRM.MetadataReader metadata, |
|
|
|
SRM.MetadataReader metadata, |
|
|
|
TypeSystemOptions options, |
|
|
|
TypeSystemOptions options, |
|
|
|
|
|
|
|
Nullability nullableContext, |
|
|
|
bool typeChildrenOnly = false) |
|
|
|
bool typeChildrenOnly = false) |
|
|
|
{ |
|
|
|
{ |
|
|
|
bool hasDynamicAttribute = false; |
|
|
|
bool hasDynamicAttribute = false; |
|
|
|
bool[] dynamicAttributeData = null; |
|
|
|
bool[] dynamicAttributeData = null; |
|
|
|
string[] tupleElementNames = null; |
|
|
|
string[] tupleElementNames = null; |
|
|
|
bool hasNullableAttribute = false; |
|
|
|
Nullability nullability; |
|
|
|
Nullability nullability = Nullability.Oblivious; |
|
|
|
|
|
|
|
Nullability[] nullableAttributeData = null; |
|
|
|
Nullability[] nullableAttributeData = null; |
|
|
|
|
|
|
|
if ((options & TypeSystemOptions.NullabilityAnnotations) != 0) { |
|
|
|
|
|
|
|
nullability = nullableContext; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
nullability = Nullability.Oblivious; |
|
|
|
|
|
|
|
} |
|
|
|
const TypeSystemOptions relevantOptions = TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple | TypeSystemOptions.NullabilityAnnotations; |
|
|
|
const TypeSystemOptions relevantOptions = TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple | TypeSystemOptions.NullabilityAnnotations; |
|
|
|
if (attributes != null && (options & relevantOptions) != 0) { |
|
|
|
if (attributes != null && (options & relevantOptions) != 0) { |
|
|
|
foreach (var attrHandle in attributes.Value) { |
|
|
|
foreach (var attrHandle in attributes.Value) { |
|
|
@ -70,7 +75,6 @@ namespace ICSharpCode.Decompiler.TypeSystem |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} else if ((options & TypeSystemOptions.NullabilityAnnotations) != 0 && attrType.IsKnownType(metadata, KnownAttribute.Nullable)) { |
|
|
|
} else if ((options & TypeSystemOptions.NullabilityAnnotations) != 0 && attrType.IsKnownType(metadata, KnownAttribute.Nullable)) { |
|
|
|
hasNullableAttribute = true; |
|
|
|
|
|
|
|
var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider); |
|
|
|
var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider); |
|
|
|
if (ctor.FixedArguments.Length == 1) { |
|
|
|
if (ctor.FixedArguments.Length == 1) { |
|
|
|
var arg = ctor.FixedArguments[0]; |
|
|
|
var arg = ctor.FixedArguments[0]; |
|
|
@ -78,13 +82,15 @@ namespace ICSharpCode.Decompiler.TypeSystem |
|
|
|
&& values.All(v => v.Value is byte b && b <= 2)) { |
|
|
|
&& values.All(v => v.Value is byte b && b <= 2)) { |
|
|
|
nullableAttributeData = values.SelectArray(v => (Nullability)(byte)v.Value); |
|
|
|
nullableAttributeData = values.SelectArray(v => (Nullability)(byte)v.Value); |
|
|
|
} else if (arg.Value is byte b && b <= 2) { |
|
|
|
} else if (arg.Value is byte b && b <= 2) { |
|
|
|
nullability = (Nullability)(byte)arg.Value; |
|
|
|
nullability = (Nullability)b; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (hasDynamicAttribute || hasNullableAttribute || (options & (TypeSystemOptions.Tuple | TypeSystemOptions.KeepModifiers)) != TypeSystemOptions.KeepModifiers) { |
|
|
|
if (hasDynamicAttribute || nullability != Nullability.Oblivious || nullableAttributeData != null |
|
|
|
|
|
|
|
|| (options & (TypeSystemOptions.Tuple | TypeSystemOptions.KeepModifiers)) != TypeSystemOptions.KeepModifiers) |
|
|
|
|
|
|
|
{ |
|
|
|
var visitor = new ApplyAttributeTypeVisitor( |
|
|
|
var visitor = new ApplyAttributeTypeVisitor( |
|
|
|
compilation, hasDynamicAttribute, dynamicAttributeData, |
|
|
|
compilation, hasDynamicAttribute, dynamicAttributeData, |
|
|
|
options, tupleElementNames, |
|
|
|
options, tupleElementNames, |
|
|
@ -148,16 +154,21 @@ namespace ICSharpCode.Decompiler.TypeSystem |
|
|
|
Nullability GetNullability() |
|
|
|
Nullability GetNullability() |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (nullabilityTypeIndex < nullableAttributeData?.Length) |
|
|
|
if (nullabilityTypeIndex < nullableAttributeData?.Length) |
|
|
|
return nullableAttributeData[nullabilityTypeIndex]; |
|
|
|
return nullableAttributeData[nullabilityTypeIndex++]; |
|
|
|
else |
|
|
|
else |
|
|
|
return defaultNullability; |
|
|
|
return defaultNullability; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ExpectDummyNullabilityForGenericValueType() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var n = GetNullability(); |
|
|
|
|
|
|
|
Debug.Assert(n == Nullability.Oblivious); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public override IType VisitArrayType(ArrayType type) |
|
|
|
public override IType VisitArrayType(ArrayType type) |
|
|
|
{ |
|
|
|
{ |
|
|
|
var nullability = GetNullability(); |
|
|
|
var nullability = GetNullability(); |
|
|
|
dynamicTypeIndex++; |
|
|
|
dynamicTypeIndex++; |
|
|
|
nullabilityTypeIndex++; |
|
|
|
|
|
|
|
return base.VisitArrayType(type).ChangeNullability(nullability); |
|
|
|
return base.VisitArrayType(type).ChangeNullability(nullability); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -181,18 +192,18 @@ namespace ICSharpCode.Decompiler.TypeSystem |
|
|
|
elementNames = ImmutableArray.CreateRange(extractedValues); |
|
|
|
elementNames = ImmutableArray.CreateRange(extractedValues); |
|
|
|
} |
|
|
|
} |
|
|
|
tupleTypeIndex += tupleCardinality; |
|
|
|
tupleTypeIndex += tupleCardinality; |
|
|
|
|
|
|
|
ExpectDummyNullabilityForGenericValueType(); |
|
|
|
var elementTypes = ImmutableArray.CreateBuilder<IType>(tupleCardinality); |
|
|
|
var elementTypes = ImmutableArray.CreateBuilder<IType>(tupleCardinality); |
|
|
|
do { |
|
|
|
do { |
|
|
|
int normalArgCount = Math.Min(type.TypeArguments.Count, TupleType.RestPosition - 1); |
|
|
|
int normalArgCount = Math.Min(type.TypeArguments.Count, TupleType.RestPosition - 1); |
|
|
|
for (int i = 0; i < normalArgCount; i++) { |
|
|
|
for (int i = 0; i < normalArgCount; i++) { |
|
|
|
dynamicTypeIndex++; |
|
|
|
dynamicTypeIndex++; |
|
|
|
nullabilityTypeIndex++; |
|
|
|
|
|
|
|
elementTypes.Add(type.TypeArguments[i].AcceptVisitor(this)); |
|
|
|
elementTypes.Add(type.TypeArguments[i].AcceptVisitor(this)); |
|
|
|
} |
|
|
|
} |
|
|
|
if (type.TypeArguments.Count == TupleType.RestPosition) { |
|
|
|
if (type.TypeArguments.Count == TupleType.RestPosition) { |
|
|
|
type = type.TypeArguments.Last() as ParameterizedType; |
|
|
|
type = type.TypeArguments.Last() as ParameterizedType; |
|
|
|
|
|
|
|
ExpectDummyNullabilityForGenericValueType(); |
|
|
|
dynamicTypeIndex++; |
|
|
|
dynamicTypeIndex++; |
|
|
|
nullabilityTypeIndex++; |
|
|
|
|
|
|
|
if (type != null && TupleType.IsTupleCompatible(type, out int nestedCardinality)) { |
|
|
|
if (type != null && TupleType.IsTupleCompatible(type, out int nestedCardinality)) { |
|
|
|
tupleTypeIndex += nestedCardinality; |
|
|
|
tupleTypeIndex += nestedCardinality; |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -218,11 +229,13 @@ namespace ICSharpCode.Decompiler.TypeSystem |
|
|
|
// Visit generic type and type arguments.
|
|
|
|
// Visit generic type and type arguments.
|
|
|
|
// Like base implementation, except that it increments dynamicTypeIndex.
|
|
|
|
// Like base implementation, except that it increments dynamicTypeIndex.
|
|
|
|
var genericType = type.GenericType.AcceptVisitor(this); |
|
|
|
var genericType = type.GenericType.AcceptVisitor(this); |
|
|
|
|
|
|
|
if (genericType.IsReferenceType != true && !genericType.IsKnownType(KnownTypeCode.NullableOfT)) { |
|
|
|
|
|
|
|
ExpectDummyNullabilityForGenericValueType(); |
|
|
|
|
|
|
|
} |
|
|
|
bool changed = type.GenericType != genericType; |
|
|
|
bool changed = type.GenericType != genericType; |
|
|
|
var arguments = new IType[type.TypeArguments.Count]; |
|
|
|
var arguments = new IType[type.TypeArguments.Count]; |
|
|
|
for (int i = 0; i < type.TypeArguments.Count; i++) { |
|
|
|
for (int i = 0; i < type.TypeArguments.Count; i++) { |
|
|
|
dynamicTypeIndex++; |
|
|
|
dynamicTypeIndex++; |
|
|
|
nullabilityTypeIndex++; |
|
|
|
|
|
|
|
arguments[i] = type.TypeArguments[i].AcceptVisitor(this); |
|
|
|
arguments[i] = type.TypeArguments[i].AcceptVisitor(this); |
|
|
|
changed = changed || arguments[i] != type.TypeArguments[i]; |
|
|
|
changed = changed || arguments[i] != type.TypeArguments[i]; |
|
|
|
} |
|
|
|
} |
|
|
@ -240,8 +253,28 @@ namespace ICSharpCode.Decompiler.TypeSystem |
|
|
|
else if (dynamicAttributeData[dynamicTypeIndex]) |
|
|
|
else if (dynamicAttributeData[dynamicTypeIndex]) |
|
|
|
newType = SpecialType.Dynamic; |
|
|
|
newType = SpecialType.Dynamic; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (type.IsReferenceType == true) { |
|
|
|
|
|
|
|
Nullability nullability = GetNullability(); |
|
|
|
|
|
|
|
return newType.ChangeNullability(nullability); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return newType; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override IType VisitOtherType(IType type) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
type = base.VisitOtherType(type); |
|
|
|
|
|
|
|
if (type.Kind == TypeKind.Unknown && type.IsReferenceType == true) { |
|
|
|
|
|
|
|
Nullability nullability = GetNullability(); |
|
|
|
|
|
|
|
type = type.ChangeNullability(nullability); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return type; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override IType VisitTypeParameter(ITypeParameter type) |
|
|
|
|
|
|
|
{ |
|
|
|
Nullability nullability = GetNullability(); |
|
|
|
Nullability nullability = GetNullability(); |
|
|
|
return newType.ChangeNullability(nullability); |
|
|
|
return type.ChangeNullability(nullability); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|