diff options
author | David Wrighton <davidwr@microsoft.com> | 2016-05-28 02:10:54 +0300 |
---|---|---|
committer | David Wrighton <davidwr@microsoft.com> | 2016-05-28 02:10:54 +0300 |
commit | 2368e17c76ba69d085945790528d6f6acc1bb608 (patch) | |
tree | 61dddbbabfb8be863eb33a98ab3f6cc205821109 /src/ILCompiler.MetadataTransform | |
parent | 00b31bc66f897b8fb7157362e3cf4308bd7d5fbf (diff) |
Add support for generating MethodImpl metadata in metadata transform (#1332)
- implementation only for ECMA metadata as we don't have TypeSystem api surface that is general purpose enough to avoid using the ECMA metadata reader directly
- metadata transform tests for generic and non-generic scenarios
Diffstat (limited to 'src/ILCompiler.MetadataTransform')
3 files changed, 84 insertions, 4 deletions
diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Type.cs b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Type.cs index 982e76ed9..6869aefa3 100644 --- a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Type.cs +++ b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Type.cs @@ -302,9 +302,24 @@ namespace ILCompiler.Metadata { record.CustomAttributes = HandleCustomAttributes(ecmaEntity.EcmaModule, customAttributes); } - } - // TODO: MethodImpls + foreach (var miHandle in ecmaRecord.GetMethodImplementations()) + { + Ecma.MetadataReader reader = ecmaEntity.EcmaModule.MetadataReader; + + Ecma.MethodImplementation miDef = reader.GetMethodImplementation(miHandle); + + Cts.MethodDesc methodBody = (Cts.MethodDesc)ecmaEntity.EcmaModule.GetObject(miDef.MethodBody); + Cts.MethodDesc methodDecl = (Cts.MethodDesc)ecmaEntity.EcmaModule.GetObject(miDef.MethodDeclaration); + MethodImpl methodImplRecord = new MethodImpl + { + MethodBody = HandleQualifiedMethod(methodBody), + MethodDeclaration = HandleQualifiedMethod(methodDecl) + }; + + record.MethodImpls.Add(methodImplRecord); + } + } } private TypeAttributes GetTypeAttributes(Cts.MetadataType type) diff --git a/src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadata.cs b/src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadata.cs index 6ea288ecc..2bb736a00 100644 --- a/src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadata.cs +++ b/src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadata.cs @@ -1650,4 +1650,22 @@ namespace SampleMetadataRex } } +namespace SampleMetadataMethodImpl +{ + interface ICloneable + { + void Clone(); + void GenericClone<T>(); + } + + class ImplementsICloneable : ICloneable + { + void ICloneable.Clone() + { + } + void ICloneable.GenericClone<T>() + { + } + } +} diff --git a/src/ILCompiler.MetadataTransform/tests/SimpleTests.cs b/src/ILCompiler.MetadataTransform/tests/SimpleTests.cs index 3c9018893..87156bfc0 100644 --- a/src/ILCompiler.MetadataTransform/tests/SimpleTests.cs +++ b/src/ILCompiler.MetadataTransform/tests/SimpleTests.cs @@ -31,7 +31,7 @@ namespace MetadataTransformTests var transformResult = MetadataTransform.Run(policy, new[] { _systemModule }); Assert.Equal(1, transformResult.Scopes.Count()); - + Assert.Equal( _systemModule.GetAllTypes().Count(x => !policy.IsBlocked(x)), transformResult.Scopes.Single().GetAllTypes().Count()); @@ -207,5 +207,52 @@ namespace MetadataTransformTests Assert.Equal(5, allowedCount); Assert.Equal(8, blockedCount); } + + [Fact] + public void TestMethodImplMetadata() + { + // Test that custom attributes referring to blocked types don't show up in metadata + + var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly"); + Cts.MetadataType iCloneable = sampleMetadataModule.GetType("SampleMetadataMethodImpl", "ICloneable"); + Cts.MetadataType implementsICloneable = sampleMetadataModule.GetType("SampleMetadataMethodImpl", "ImplementsICloneable"); + Cts.MethodDesc iCloneableDotClone = iCloneable.GetMethod("Clone", null); + Cts.MethodDesc iCloneableImplementation = implementsICloneable.GetMethod("SampleMetadataMethodImpl.ICloneable.Clone", null); + Cts.MethodDesc iCloneableDotGenericClone = iCloneable.GetMethod("GenericClone", null); + Cts.MethodDesc iCloneableGenericImplementation = implementsICloneable.GetMethod("SampleMetadataMethodImpl.ICloneable.GenericClone", null); + + var policy = new SingleFileMetadataPolicy(); + var transformResult = MetadataTransform.Run(policy, + new[] { _systemModule, sampleMetadataModule }); + + var iCloneableType = transformResult.GetTransformedTypeDefinition(iCloneable); + var implementsICloneableType = transformResult.GetTransformedTypeDefinition(implementsICloneable); + + Assert.Equal(2, implementsICloneableType.MethodImpls.Count); + + // non-generic MethodImpl + Method iCloneableDotCloneMethod = transformResult.GetTransformedMethodDefinition(iCloneableDotClone); + Method iCloneableImplementationMethod = transformResult.GetTransformedMethodDefinition(iCloneableImplementation); + QualifiedMethod methodImplMethodDecl = (QualifiedMethod)implementsICloneableType.MethodImpls[0].MethodDeclaration; + QualifiedMethod methodImplMethodBody = (QualifiedMethod)implementsICloneableType.MethodImpls[0].MethodBody; + + Assert.Equal(iCloneableDotCloneMethod, methodImplMethodDecl.Method); + Assert.Equal(iCloneableType, methodImplMethodDecl.EnclosingType); + + Assert.Equal(iCloneableImplementationMethod, methodImplMethodBody.Method); + Assert.Equal(implementsICloneableType, methodImplMethodBody.EnclosingType); + + // generic MethodImpl + Method iCloneableDotGenericCloneMethod = transformResult.GetTransformedMethodDefinition(iCloneableDotGenericClone); + Method iCloneableGenericImplementationMethod = transformResult.GetTransformedMethodDefinition(iCloneableGenericImplementation); + QualifiedMethod methodImplGenericMethodDecl = (QualifiedMethod)implementsICloneableType.MethodImpls[1].MethodDeclaration; + QualifiedMethod methodImplGenericMethodBody = (QualifiedMethod)implementsICloneableType.MethodImpls[1].MethodBody; + + Assert.Equal(iCloneableDotGenericCloneMethod, methodImplGenericMethodDecl.Method); + Assert.Equal(iCloneableType, methodImplGenericMethodDecl.EnclosingType); + + Assert.Equal(iCloneableGenericImplementationMethod, methodImplGenericMethodBody.Method); + Assert.Equal(implementsICloneableType, methodImplGenericMethodBody.EnclosingType); + } } -} +}
\ No newline at end of file |