|
|
|
@ -40,14 +40,14 @@ namespace ICSharpCode.Decompiler.TypeSystem |
|
|
|
|
|
|
|
|
|
|
|
var metadata = module.MetadataFile.Metadata; |
|
|
|
var metadata = module.MetadataFile.Metadata; |
|
|
|
|
|
|
|
|
|
|
|
foreach (var extGroup in extensionContainer.NestedTypes) |
|
|
|
foreach (var nestedType in extensionContainer.NestedTypes) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (TryEncodingV1(extGroup)) |
|
|
|
if (TryEncodingV1(nestedType)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
TryEncodingV2(extGroup); |
|
|
|
TryEncodingV2(nestedType); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool TryEncodingV1(ITypeDefinition extGroup) |
|
|
|
bool TryEncodingV1(ITypeDefinition extGroup) |
|
|
|
@ -90,43 +90,52 @@ namespace ICSharpCode.Decompiler.TypeSystem |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool TryEncodingV2(ITypeDefinition extGroup) |
|
|
|
bool TryEncodingV2(ITypeDefinition extensionGroupsContainer) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (!(extGroup is { Kind: TypeKind.Class, IsSealed: true } |
|
|
|
// there exists one nested type per extension target type
|
|
|
|
&& extGroup.Name.StartsWith("<G>$", StringComparison.Ordinal))) |
|
|
|
if (!(extensionGroupsContainer is { Kind: TypeKind.Class, IsSealed: true } |
|
|
|
|
|
|
|
&& extensionGroupsContainer.Name.StartsWith("<G>$", StringComparison.Ordinal))) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var markerType = extGroup.NestedTypes.SingleOrDefault(t => t.Name.StartsWith("<M>$", StringComparison.Ordinal) && t.IsStatic); |
|
|
|
// if there are multiple extension-blocks with the same target type,
|
|
|
|
var marker = markerType?.Methods.SingleOrDefault(m => m.Name == "<Extension>$" && m.IsStatic && m.Parameters.Count == 1); |
|
|
|
// but different names for the extension parameter,
|
|
|
|
|
|
|
|
// there is a separate markerType, so there are multiple marker types per
|
|
|
|
|
|
|
|
// target type
|
|
|
|
|
|
|
|
foreach (var markerType in extensionGroupsContainer.NestedTypes) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!(markerType.Name.StartsWith("<M>$", StringComparison.Ordinal) && markerType.IsStatic)) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
var marker = markerType.Methods.SingleOrDefault(m => m.Name == "<Extension>$" && m.IsStatic && m.Parameters.Count == 1); |
|
|
|
|
|
|
|
if (marker == null) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
if (markerType == null || marker == null) |
|
|
|
TypeDefinition td = metadata.GetTypeDefinition((TypeDefinitionHandle)extensionGroupsContainer.MetadataToken); |
|
|
|
return false; |
|
|
|
List<IMethod> extensionMethods = []; |
|
|
|
|
|
|
|
ITypeParameter[] extensionGroupTypeParameters = new ITypeParameter[extensionGroupsContainer.TypeParameterCount]; |
|
|
|
|
|
|
|
|
|
|
|
TypeDefinition td = metadata.GetTypeDefinition((TypeDefinitionHandle)extGroup.MetadataToken); |
|
|
|
// For easier access to accessors we use SRM
|
|
|
|
List<IMethod> extensionMethods = []; |
|
|
|
foreach (var h in td.GetMethods()) |
|
|
|
ITypeParameter[] extensionGroupTypeParameters = new ITypeParameter[extGroup.TypeParameterCount]; |
|
|
|
{ |
|
|
|
|
|
|
|
var method = module.GetDefinition(h); |
|
|
|
|
|
|
|
|
|
|
|
// For easier access to accessors we use SRM
|
|
|
|
if (method.SymbolKind is SymbolKind.Constructor) |
|
|
|
foreach (var h in td.GetMethods()) |
|
|
|
continue; |
|
|
|
{ |
|
|
|
|
|
|
|
var method = module.GetDefinition(h); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (method.SymbolKind is SymbolKind.Constructor) |
|
|
|
var attribute = method.GetAttribute(KnownAttribute.ExtensionMarker); |
|
|
|
continue; |
|
|
|
if (attribute == null) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
var attribute = method.GetAttribute(KnownAttribute.ExtensionMarker); |
|
|
|
if (attribute.FixedArguments[0].Value?.ToString() != markerType.Name) |
|
|
|
if (attribute == null) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (attribute.FixedArguments[0].Value?.ToString() != markerType.Name) |
|
|
|
extensionMethods.Add(method); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
extensionMethods.Add(method); |
|
|
|
CollectImplementationMethods(extensionGroupsContainer, marker, extensionMethods, extensionGroupTypeParameters); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CollectImplementationMethods(extGroup, marker, extensionMethods, extensionGroupTypeParameters); |
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|