Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Wrighton <davidwr@microsoft.com>2016-05-26 02:10:56 +0300
committerDavid Wrighton <davidwr@microsoft.com>2016-05-26 02:10:56 +0300
commitba30ad4bd2a62a479252dc4e1de2625ad7e6a7e6 (patch)
tree199f70f086134d9627d7f25540c49773a58b3d0d /src/ILCompiler.MetadataTransform
parent97c1f333b2b39ee9e84e7a4cdfb3cc1fea9017f0 (diff)
Add support for ExplicitScopeAttribute to metadata generation (#1321)
* Add support for ExplicitScopeAttribute to metadata generation - Add new IMetadataPolicy member to control the defining module of a type - Added mixin implementation that works for ExplicitScopeAttribute - Added WinRT explicit scope defined types in both the primary metadata assembly and same metadata assembly - Added single file and multi file tests to ensure that both definition and reference to these relocated types is correct - New tests implemented in seperate assemblies to reduce impact on existing unittests - Fix handling of throwIfNotFound parameter in ResolveAssembly in TestTypeSystemContext
Diffstat (limited to 'src/ILCompiler.MetadataTransform')
-rw-r--r--src/ILCompiler.MetadataTransform/MetadataTransform.sln14
-rw-r--r--src/ILCompiler.MetadataTransform/src/ILCompiler.MetadataTransform.csproj1
-rw-r--r--src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/ExplicitScopeAssemblyPolicyMixin.cs164
-rw-r--r--src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/IMetadataPolicy.cs6
-rw-r--r--src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/MetadataTransform.cs2
-rw-r--r--src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Scope.cs4
-rw-r--r--src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Type.cs8
-rw-r--r--src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.cs4
-rw-r--r--src/ILCompiler.MetadataTransform/tests/ExplicitScopeTests.cs134
-rw-r--r--src/ILCompiler.MetadataTransform/tests/ILCompiler.MetadataTransform.Tests.csproj13
-rw-r--r--src/ILCompiler.MetadataTransform/tests/MockPolicy.cs12
-rw-r--r--src/ILCompiler.MetadataTransform/tests/MultifileMetadataPolicy.cs7
-rw-r--r--src/ILCompiler.MetadataTransform/tests/PrimaryMetadataAssembly/Platform.cs8
-rw-r--r--src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadata.cs1
-rw-r--r--src/ILCompiler.MetadataTransform/tests/SampleWinRTMetadataAssembly/SampleWinRTMetadata.cs31
-rw-r--r--src/ILCompiler.MetadataTransform/tests/SampleWinRTMetadataAssembly/SampleWinRTMetadataAssembly.csproj28
-rw-r--r--src/ILCompiler.MetadataTransform/tests/SingleFileMetadataPolicy.cs18
-rw-r--r--src/ILCompiler.MetadataTransform/tests/TestTypeSystemContext.cs31
-rw-r--r--src/ILCompiler.MetadataTransform/tests/WindowsWinrtMetadataAssembly/WindowsWinrtMetadata.cs25
-rw-r--r--src/ILCompiler.MetadataTransform/tests/WindowsWinrtMetadataAssembly/WindowsWinrtMetadataAssembly.csproj26
20 files changed, 515 insertions, 22 deletions
diff --git a/src/ILCompiler.MetadataTransform/MetadataTransform.sln b/src/ILCompiler.MetadataTransform/MetadataTransform.sln
index cd3add580..39d81a4ce 100644
--- a/src/ILCompiler.MetadataTransform/MetadataTransform.sln
+++ b/src/ILCompiler.MetadataTransform/MetadataTransform.sln
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
-VisualStudioVersion = 14.0.24720.0
+VisualStudioVersion = 14.0.24711.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILCompiler.MetadataTransform", "src\ILCompiler.MetadataTransform.csproj", "{A965EA82-219D-48F7-AD51-BC030C16CC6F}"
EndProject
@@ -15,6 +15,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrimaryMetadataAssembly", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleMetadataAssembly", "tests\SampleMetadataAssembly\SampleMetadataAssembly.csproj", "{D29B7395-A925-5B0E-972D-387D2D4BFEC8}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsWinrtMetadataAssembly", "tests\WindowsWinrtMetadataAssembly\WindowsWinrtMetadataAssembly.csproj", "{19D0BAA8-8762-4D64-80AF-53D7A2BBC4AE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleWinRTMetadataAssembly", "tests\SampleWinRTMetadataAssembly\SampleWinRTMetadataAssembly.csproj", "{46CDD663-FCCC-4E74-901F-3D9D5A36A0D9}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -45,6 +49,14 @@ Global
{D29B7395-A925-5B0E-972D-387D2D4BFEC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D29B7395-A925-5B0E-972D-387D2D4BFEC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D29B7395-A925-5B0E-972D-387D2D4BFEC8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {19D0BAA8-8762-4D64-80AF-53D7A2BBC4AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {19D0BAA8-8762-4D64-80AF-53D7A2BBC4AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {19D0BAA8-8762-4D64-80AF-53D7A2BBC4AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {19D0BAA8-8762-4D64-80AF-53D7A2BBC4AE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {46CDD663-FCCC-4E74-901F-3D9D5A36A0D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {46CDD663-FCCC-4E74-901F-3D9D5A36A0D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {46CDD663-FCCC-4E74-901F-3D9D5A36A0D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {46CDD663-FCCC-4E74-901F-3D9D5A36A0D9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler.MetadataTransform.csproj b/src/ILCompiler.MetadataTransform/src/ILCompiler.MetadataTransform.csproj
index 36b0647d8..7f9487fe9 100644
--- a/src/ILCompiler.MetadataTransform/src/ILCompiler.MetadataTransform.csproj
+++ b/src/ILCompiler.MetadataTransform/src/ILCompiler.MetadataTransform.csproj
@@ -28,6 +28,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ILCompiler\Metadata\EntityMap.cs" />
+ <Compile Include="ILCompiler\Metadata\ExplicitScopeAssemblyPolicyMixin.cs" />
<Compile Include="ILCompiler\Metadata\IMetadataPolicy.cs" />
<Compile Include="ILCompiler\Metadata\MetadataTransform.cs" />
<Compile Include="ILCompiler\Metadata\MetadataTransformResult.cs" />
diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/ExplicitScopeAssemblyPolicyMixin.cs b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/ExplicitScopeAssemblyPolicyMixin.cs
new file mode 100644
index 000000000..7b08618e5
--- /dev/null
+++ b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/ExplicitScopeAssemblyPolicyMixin.cs
@@ -0,0 +1,164 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using Cts = Internal.TypeSystem;
+using Ecma = System.Reflection.Metadata;
+
+namespace ILCompiler.Metadata
+{
+ /// <summary>
+ /// Mixin helper class to allow easy support for ExplicitScopeAttribute for metadata transformation
+ ///
+ /// ExplicitScopeAttribute is used to relocate where a given type appears in metadata from one
+ /// metadata assembly to another. It must not be used to relocate into an assembly which otherwise
+ /// exists within the compilation operation. (Current implementation is not reliable in those
+ /// circumstances, but there is an assert that in debug builds will detect violations.)
+ /// </summary>
+ public class ExplicitScopeAssemblyPolicyMixin
+ {
+ private class AssemblyNameEqualityComparer : IEqualityComparer<AssemblyName>
+ {
+ public static AssemblyNameEqualityComparer Instance { get; } = new AssemblyNameEqualityComparer();
+
+ public bool ByteArrayCompare(byte[] arr1, byte[] arr2)
+ {
+ if (arr1.Length != arr2.Length)
+ return false;
+
+ for (int i = 0; i < arr1.Length; i++)
+ {
+ if (arr1[i] != arr2[i])
+ return false;
+ }
+ return true;
+ }
+
+ public bool Equals(AssemblyName x, AssemblyName y)
+ {
+ if (x.Name != y.Name)
+ return false;
+
+ if (x.ContentType != y.ContentType)
+ return false;
+
+ if (x.CultureName != y.CultureName)
+ return false;
+
+ if (x.Flags != y.Flags)
+ return false;
+
+ if (x.Flags.HasFlag(AssemblyNameFlags.PublicKey))
+ {
+ if (!ByteArrayCompare(x.GetPublicKey(), y.GetPublicKey()))
+ return false;
+ }
+ else
+ {
+ if (!ByteArrayCompare(x.GetPublicKeyToken(), y.GetPublicKeyToken()))
+ return false;
+ }
+
+ if (x.ProcessorArchitecture != y.ProcessorArchitecture)
+ return false;
+
+ if (!x.Version.Equals(y.Version))
+ return false;
+
+ return true;
+ }
+
+ public int GetHashCode(AssemblyName obj)
+ {
+ return obj.Name.GetHashCode();
+ }
+ }
+
+ private class ExplicitScopeAssembly : Cts.ModuleDesc, Cts.IAssemblyDesc
+ {
+ AssemblyName _assemblyName;
+
+ public ExplicitScopeAssembly(Cts.TypeSystemContext context, AssemblyName assemblyName) : base(context)
+ {
+ _assemblyName = assemblyName;
+ }
+
+ AssemblyName Cts.IAssemblyDesc.GetName()
+ {
+ return _assemblyName;
+ }
+
+ public override Cts.MetadataType GetType(string nameSpace, string name, bool throwIfNotFound = true)
+ {
+ if (throwIfNotFound)
+ throw new TypeLoadException("GetType on an ExplicitScopeAssembly is not supported");
+ return null;
+ }
+
+ public override Cts.TypeDesc GetGlobalModuleType()
+ {
+ return null;
+ }
+
+ public override IEnumerable<Cts.MetadataType> GetAllTypes()
+ {
+ return Array.Empty<Cts.MetadataType>();
+ }
+ }
+
+ private Dictionary<AssemblyName, ExplicitScopeAssembly> _dynamicallyGeneratedExplicitScopes =
+ new Dictionary<AssemblyName, ExplicitScopeAssembly>(AssemblyNameEqualityComparer.Instance);
+
+ private Cts.ModuleDesc OverrideModuleOfTypeViaExplicitScope(Cts.MetadataType typeDef)
+ {
+ if (typeDef.HasCustomAttribute("Internal.Reflection", "ExplicitScopeAttribute"))
+ {
+ // There is no current cross type system way to represent custom attributes
+ Cts.Ecma.EcmaType ecmaType = (Cts.Ecma.EcmaType)typeDef;
+
+ var customAttributeValue = Internal.TypeSystem.Ecma.MetadataExtensions.GetDecodedCustomAttribute(
+ ecmaType, "Internal.Reflection", "ExplicitScopeAttribute");
+
+ if (!customAttributeValue.HasValue)
+ return null;
+
+ if (customAttributeValue.Value.FixedArguments.Length != 1)
+ return null;
+
+ if (customAttributeValue.Value.FixedArguments[0].Type != typeDef.Context.GetWellKnownType(Cts.WellKnownType.String))
+ return null;
+
+ string assemblyNameString = (string)customAttributeValue.Value.FixedArguments[0].Value;
+ AssemblyName assemblyName = new AssemblyName(assemblyNameString);
+ Debug.Assert(typeDef.Context.ResolveAssembly(assemblyName, false) == null, "ExplicitScopeAttribute must not refer to an assembly which is actually present in the type system.");
+ lock(_dynamicallyGeneratedExplicitScopes)
+ {
+ ExplicitScopeAssembly explicitScopeAssembly;
+
+ if (_dynamicallyGeneratedExplicitScopes.TryGetValue(assemblyName, out explicitScopeAssembly))
+ {
+ return explicitScopeAssembly;
+ }
+ explicitScopeAssembly = new ExplicitScopeAssembly(typeDef.Context, assemblyName);
+ _dynamicallyGeneratedExplicitScopes.Add(assemblyName, explicitScopeAssembly);
+ return explicitScopeAssembly;
+ }
+ }
+
+ return null;
+ }
+
+ public Cts.ModuleDesc GetModuleOfType(Cts.MetadataType typeDef)
+ {
+ Cts.ModuleDesc overrideModule = OverrideModuleOfTypeViaExplicitScope(typeDef);
+ if (overrideModule != null)
+ return overrideModule;
+
+ return typeDef.Module;
+ }
+ }
+}
diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/IMetadataPolicy.cs b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/IMetadataPolicy.cs
index e4d407af8..48c3474ae 100644
--- a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/IMetadataPolicy.cs
+++ b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/IMetadataPolicy.cs
@@ -43,5 +43,11 @@ namespace ILCompiler.Metadata
/// blocked types are dropped from metadata.
/// </summary>
bool IsBlocked(Cts.MetadataType typeDef);
+
+ /// <summary>
+ /// Return the Module that should be treated as defining the type. Typically implementations
+ /// will return typeDef.Module, but in some circumstances it may return a different value.
+ /// </summary>
+ Cts.ModuleDesc GetModuleOfType(Cts.MetadataType typeDef);
}
}
diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/MetadataTransform.cs b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/MetadataTransform.cs
index 68858f046..f9cbe1250 100644
--- a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/MetadataTransform.cs
+++ b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/MetadataTransform.cs
@@ -34,7 +34,7 @@ namespace ILCompiler.Metadata
// - change the way TypeDefs are hooked up into namespaces and scopes
// - queue up calls to the various Initialize* methods on a threadpool
- var transform = new Transform<TPolicy>(policy, modules);
+ var transform = new Transform<TPolicy>(policy);
foreach (var module in modules)
{
diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Scope.cs b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Scope.cs
index 1375c325d..19565baa0 100644
--- a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Scope.cs
+++ b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Scope.cs
@@ -29,10 +29,6 @@ namespace ILCompiler.Metadata
private void InitializeScopeDefinition(Cts.ModuleDesc module, ScopeDefinition scopeDefinition)
{
- // Make sure we're expected to create a scope definition here. If the assert fires, the metadata
- // policy should have directed us to create a scope reference (or the list of inputs was incomplete).
- Debug.Assert(_modulesToTransform.Contains(module), "Incomplete list of input modules with respect to metadata policy");
-
var assemblyDesc = module as Cts.IAssemblyDesc;
if (assemblyDesc != null)
{
diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Type.cs b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Type.cs
index 7baf9e0cb..982e76ed9 100644
--- a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Type.cs
+++ b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Type.cs
@@ -192,7 +192,7 @@ namespace ILCompiler.Metadata
}
else
{
- parentReferenceRecord.ParentNamespaceOrType = HandleNamespaceReference(containingType.Module, containingType.Namespace);
+ parentReferenceRecord.ParentNamespaceOrType = HandleNamespaceReference(_policy.GetModuleOfType(containingType), containingType.Namespace);
}
return parentReferenceRecord;
@@ -208,7 +208,7 @@ namespace ILCompiler.Metadata
}
else
{
- record.ParentNamespaceOrType = HandleNamespaceReference(entity.Module, entity.Namespace);
+ record.ParentNamespaceOrType = HandleNamespaceReference(_policy.GetModuleOfType(entity), entity.Namespace);
}
record.TypeName = HandleString(entity.Name);
@@ -225,12 +225,12 @@ namespace ILCompiler.Metadata
enclosingType.NestedTypes.Add(record);
var namespaceDefinition =
- HandleNamespaceDefinition(entity.ContainingType.Module, entity.ContainingType.Namespace);
+ HandleNamespaceDefinition(_policy.GetModuleOfType(entity.ContainingType), entity.ContainingType.Namespace);
record.NamespaceDefinition = namespaceDefinition;
}
else
{
- var namespaceDefinition = HandleNamespaceDefinition(entity.Module, entity.Namespace);
+ var namespaceDefinition = HandleNamespaceDefinition(_policy.GetModuleOfType(entity), entity.Namespace);
record.NamespaceDefinition = namespaceDefinition;
namespaceDefinition.TypeDefinitions.Add(record);
}
diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.cs b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.cs
index d64c5a3fb..ef7554629 100644
--- a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.cs
+++ b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.cs
@@ -20,12 +20,10 @@ namespace ILCompiler.Metadata
where TPolicy : struct, IMetadataPolicy
{
private TPolicy _policy;
- private HashSet<Cts.ModuleDesc> _modulesToTransform;
- public Transform(TPolicy policy, IEnumerable<Cts.ModuleDesc> modules)
+ public Transform(TPolicy policy)
{
_policy = policy;
- _modulesToTransform = new HashSet<Cts.ModuleDesc>(modules);
}
private bool IsBlocked(Cts.TypeDesc type)
diff --git a/src/ILCompiler.MetadataTransform/tests/ExplicitScopeTests.cs b/src/ILCompiler.MetadataTransform/tests/ExplicitScopeTests.cs
new file mode 100644
index 000000000..6745b23ee
--- /dev/null
+++ b/src/ILCompiler.MetadataTransform/tests/ExplicitScopeTests.cs
@@ -0,0 +1,134 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Linq;
+using Internal.Metadata.NativeFormat.Writer;
+using ILCompiler.Metadata;
+
+using Cts = Internal.TypeSystem;
+using NativeFormat = Internal.Metadata.NativeFormat;
+
+using Xunit;
+
+namespace MetadataTransformTests
+{
+ public class ExplicitScopeTests
+ {
+ private TestTypeSystemContext _context;
+ private Cts.Ecma.EcmaModule _systemModule;
+
+ public ExplicitScopeTests()
+ {
+ _context = new TestTypeSystemContext();
+ _systemModule = _context.CreateModuleForSimpleName("PrimaryMetadataAssembly");
+ _context.SetSystemModule(_systemModule);
+ }
+
+ public ScopeDefinition GetScopeDefinitionOfType(TypeDefinition typeDefinition)
+ {
+ Assert.NotNull(typeDefinition);
+ ScopeDefinition scope = null;
+ NamespaceDefinition currentNamespaceDefinition = typeDefinition.NamespaceDefinition;
+
+ while (scope == null)
+ {
+ Assert.NotNull(currentNamespaceDefinition);
+ scope = currentNamespaceDefinition.ParentScopeOrNamespace as ScopeDefinition;
+ currentNamespaceDefinition = currentNamespaceDefinition.ParentScopeOrNamespace as NamespaceDefinition;
+ }
+
+ return scope;
+ }
+
+ public ScopeReference GetScopeReferenceOfType(TypeReference typeReference)
+ {
+ Assert.NotNull(typeReference);
+ ScopeReference scope = null;
+ NamespaceReference currentNamespaceReference = typeReference.ParentNamespaceOrType as NamespaceReference;
+
+ while (scope == null)
+ {
+ Assert.NotNull(currentNamespaceReference);
+ scope = currentNamespaceReference.ParentScopeOrNamespace as ScopeReference;
+ currentNamespaceReference = currentNamespaceReference.ParentScopeOrNamespace as NamespaceReference;
+ }
+
+ return scope;
+ }
+
+ public void CheckTypeDefinitionForProperWinRTHome(TypeDefinition typeDefinition, string module)
+ {
+ ScopeDefinition scope = GetScopeDefinitionOfType(typeDefinition);
+ Assert.Equal(module, scope.Name.Value);
+ int windowsRuntimeFlag = ((int)System.Reflection.AssemblyContentType.WindowsRuntime << 9);
+ Assert.True((((int)scope.Flags) & windowsRuntimeFlag) == windowsRuntimeFlag);
+ }
+
+
+ public void CheckTypeReferenceForProperWinRTHome(TypeReference typeReference, string module)
+ {
+ ScopeReference scope = GetScopeReferenceOfType(typeReference);
+ Assert.Equal(module, scope.Name.Value);
+ int windowsRuntimeFlag = ((int)System.Reflection.AssemblyContentType.WindowsRuntime << 9);
+ Assert.True((((int)scope.Flags) & windowsRuntimeFlag) == windowsRuntimeFlag);
+ }
+
+ [Fact]
+ public void TestExplicitScopeAttributesForWinRTSingleFilePolicy()
+ {
+ // Test that custom attributes referring to blocked types don't show up in metadata
+
+ var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly");
+ var sampleWinRTMetadataModule = _context.GetModuleForSimpleName("SampleWinRTMetadataAssembly");
+ var windowsWinRTMetadataModule = _context.GetModuleForSimpleName("WindowsWinRTMetadataAssembly");
+
+ Cts.MetadataType controlType = windowsWinRTMetadataModule.GetType("Windows", "Control");
+ Cts.MetadataType derivedFromControl = sampleWinRTMetadataModule.GetType("SampleMetadataWinRT", "DerivedFromControl");
+ Cts.MetadataType derivedFromControlInCustomScope = sampleWinRTMetadataModule.GetType("SampleMetadataWinRT", "DerivedFromControlAndInCustomScope");
+
+ var policy = new SingleFileMetadataPolicy();
+
+ var transformResult = MetadataTransform.Run(policy,
+ new[] { _systemModule, sampleMetadataModule, sampleWinRTMetadataModule, windowsWinRTMetadataModule });
+
+ var controlTypeMetadata = transformResult.GetTransformedTypeDefinition(controlType);
+ var derivedFromControlMetadata = transformResult.GetTransformedTypeDefinition(derivedFromControl);
+ var derivedFromControlInCustomScopeMetadata = transformResult.GetTransformedTypeDefinition(derivedFromControlInCustomScope);
+
+ CheckTypeDefinitionForProperWinRTHome(controlTypeMetadata, "Windows");
+ ScopeDefinition scopeDefOfDerivedFromControlType = GetScopeDefinitionOfType(derivedFromControlMetadata);
+ Assert.Equal("SampleWinRTMetadataAssembly", scopeDefOfDerivedFromControlType.Name.Value);
+ CheckTypeDefinitionForProperWinRTHome(derivedFromControlInCustomScopeMetadata, "SampleMetadataWinRT");
+ }
+
+
+ [Fact]
+ public void TestExplicitScopeAttributesForWinRTMultiFilePolicy()
+ {
+ // Test that custom attributes referring to blocked types don't show up in metadata
+
+ var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly");
+ var sampleWinRTMetadataModule = _context.GetModuleForSimpleName("SampleWinRTMetadataAssembly");
+ var windowsWinRTMetadataModule = _context.GetModuleForSimpleName("WindowsWinRTMetadataAssembly");
+
+ Cts.MetadataType controlType = windowsWinRTMetadataModule.GetType("Windows", "Control");
+ Cts.MetadataType derivedFromControl = sampleWinRTMetadataModule.GetType("SampleMetadataWinRT", "DerivedFromControl");
+ Cts.MetadataType derivedFromControlInCustomScope = sampleWinRTMetadataModule.GetType("SampleMetadataWinRT", "DerivedFromControlAndInCustomScope");
+
+ var policy = new MultifileMetadataPolicy(sampleMetadataModule, sampleWinRTMetadataModule);
+
+ var transformResult = MetadataTransform.Run(policy,
+ new[] { _systemModule, sampleMetadataModule, sampleWinRTMetadataModule, windowsWinRTMetadataModule });
+
+ var controlTypeMetadata = transformResult.GetTransformedTypeReference(controlType);
+ var derivedFromControlMetadata = transformResult.GetTransformedTypeDefinition(derivedFromControl);
+ var derivedFromControlInCustomScopeMetadata = transformResult.GetTransformedTypeDefinition(derivedFromControlInCustomScope);
+
+ CheckTypeReferenceForProperWinRTHome(controlTypeMetadata, "Windows");
+ ScopeDefinition scopeDefOfDerivedFromControlType = GetScopeDefinitionOfType(derivedFromControlMetadata);
+ Assert.Equal("SampleWinRTMetadataAssembly", scopeDefOfDerivedFromControlType.Name.Value);
+ CheckTypeDefinitionForProperWinRTHome(derivedFromControlInCustomScopeMetadata, "SampleMetadataWinRT");
+ }
+ }
+}
diff --git a/src/ILCompiler.MetadataTransform/tests/ILCompiler.MetadataTransform.Tests.csproj b/src/ILCompiler.MetadataTransform/tests/ILCompiler.MetadataTransform.Tests.csproj
index bba38298f..8ae05e9ff 100644
--- a/src/ILCompiler.MetadataTransform/tests/ILCompiler.MetadataTransform.Tests.csproj
+++ b/src/ILCompiler.MetadataTransform/tests/ILCompiler.MetadataTransform.Tests.csproj
@@ -39,11 +39,24 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Targets>Build;DebugSymbolsProjectOutputGroup</Targets>
</ProjectReference>
+ <ProjectReference Include="SampleWinRTMetadataAssembly\SampleWinRTMetadataAssembly.csproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <OutputItemType>Content</OutputItemType>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ <Targets>Build;DebugSymbolsProjectOutputGroup</Targets>
+ </ProjectReference>
+ <ProjectReference Include="WindowsWinrtMetadataAssembly\WindowsWinrtMetadataAssembly.csproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <OutputItemType>Content</OutputItemType>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ <Targets>Build;DebugSymbolsProjectOutputGroup</Targets>
+ </ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="ExplicitScopeTests.cs" />
<Compile Include="MockPolicy.cs" />
<Compile Include="MultifileMetadataPolicy.cs" />
<Compile Include="NativeFormatExtensions.cs" />
diff --git a/src/ILCompiler.MetadataTransform/tests/MockPolicy.cs b/src/ILCompiler.MetadataTransform/tests/MockPolicy.cs
index c262269aa..c87ce5f8b 100644
--- a/src/ILCompiler.MetadataTransform/tests/MockPolicy.cs
+++ b/src/ILCompiler.MetadataTransform/tests/MockPolicy.cs
@@ -15,17 +15,20 @@ namespace MetadataTransformTests
private Func<FieldDesc, bool> _fieldGeneratesMetadata;
private Func<MetadataType, bool> _isBlockedType;
+ private Func<MetadataType, ModuleDesc> _moduleOfType;
public MockPolicy(
Func<MetadataType, bool> typeGeneratesMetadata,
Func<MethodDesc, bool> methodGeneratesMetadata = null,
Func<FieldDesc, bool> fieldGeneratesMetadata = null,
- Func<MetadataType, bool> isBlockedType = null)
+ Func<MetadataType, bool> isBlockedType = null,
+ Func<MetadataType, ModuleDesc> moduleOfType = null)
{
_typeGeneratesMetadata = typeGeneratesMetadata;
_methodGeneratesMetadata = methodGeneratesMetadata;
_fieldGeneratesMetadata = fieldGeneratesMetadata;
_isBlockedType = isBlockedType;
+ _moduleOfType = moduleOfType;
}
public bool GeneratesMetadata(MethodDesc methodDef)
@@ -53,5 +56,12 @@ namespace MetadataTransformTests
return _isBlockedType(typeDef);
return false;
}
+
+ public ModuleDesc GetModuleOfType(MetadataType typeDef)
+ {
+ if (_moduleOfType != null)
+ return _moduleOfType(typeDef);
+ return typeDef.Module;
+ }
}
}
diff --git a/src/ILCompiler.MetadataTransform/tests/MultifileMetadataPolicy.cs b/src/ILCompiler.MetadataTransform/tests/MultifileMetadataPolicy.cs
index 2eb940d96..ac4d25775 100644
--- a/src/ILCompiler.MetadataTransform/tests/MultifileMetadataPolicy.cs
+++ b/src/ILCompiler.MetadataTransform/tests/MultifileMetadataPolicy.cs
@@ -17,11 +17,13 @@ namespace MetadataTransformTests
/// </summary>
struct MultifileMetadataPolicy : IMetadataPolicy
{
+ ExplicitScopeAssemblyPolicyMixin _explicitScopePolicyMixin;
HashSet<ModuleDesc> _modules;
public MultifileMetadataPolicy(params ModuleDesc[] modules)
{
_modules = new HashSet<ModuleDesc>(modules);
+ _explicitScopePolicyMixin = new ExplicitScopeAssemblyPolicyMixin();
}
public bool GeneratesMetadata(MethodDesc methodDef)
@@ -49,5 +51,10 @@ namespace MetadataTransformTests
return false;
}
+
+ public ModuleDesc GetModuleOfType(MetadataType typeDef)
+ {
+ return _explicitScopePolicyMixin.GetModuleOfType(typeDef);
+ }
}
}
diff --git a/src/ILCompiler.MetadataTransform/tests/PrimaryMetadataAssembly/Platform.cs b/src/ILCompiler.MetadataTransform/tests/PrimaryMetadataAssembly/Platform.cs
index 25c809c43..b6bea6761 100644
--- a/src/ILCompiler.MetadataTransform/tests/PrimaryMetadataAssembly/Platform.cs
+++ b/src/ILCompiler.MetadataTransform/tests/PrimaryMetadataAssembly/Platform.cs
@@ -140,3 +140,11 @@ namespace System.Runtime.CompilerServices
}
}
+namespace Internal.Reflection
+{
+ public sealed class ExplicitScopeAttribute : System.Attribute
+ {
+ public ExplicitScopeAttribute(string explicitScope)
+ { }
+ }
+}
diff --git a/src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadata.cs b/src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadata.cs
index 459d338a7..6ea288ecc 100644
--- a/src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadata.cs
+++ b/src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadata.cs
@@ -1650,3 +1650,4 @@ namespace SampleMetadataRex
}
}
+
diff --git a/src/ILCompiler.MetadataTransform/tests/SampleWinRTMetadataAssembly/SampleWinRTMetadata.cs b/src/ILCompiler.MetadataTransform/tests/SampleWinRTMetadataAssembly/SampleWinRTMetadata.cs
new file mode 100644
index 000000000..028095cba
--- /dev/null
+++ b/src/ILCompiler.MetadataTransform/tests/SampleWinRTMetadataAssembly/SampleWinRTMetadata.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+#pragma warning disable 414
+#pragma warning disable 67
+#pragma warning disable 3009
+#pragma warning disable 3016
+#pragma warning disable 3001
+#pragma warning disable 3015
+#pragma warning disable 169
+#pragma warning disable 649
+
+namespace SampleMetadataWinRT
+{
+ // This class should appear to be in a regular managed module
+ public class DerivedFromControl : Windows.Control
+ { }
+
+ // This class should appear to be in a winmd called SampleMetadataWinRT
+ [global::Internal.Reflection.ExplicitScope("SampleMetadataWinRT, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime")]
+ public class DerivedFromControlAndInCustomScope : Windows.Control
+ {
+ }
+}
+
diff --git a/src/ILCompiler.MetadataTransform/tests/SampleWinRTMetadataAssembly/SampleWinRTMetadataAssembly.csproj b/src/ILCompiler.MetadataTransform/tests/SampleWinRTMetadataAssembly/SampleWinRTMetadataAssembly.csproj
new file mode 100644
index 000000000..a6786563b
--- /dev/null
+++ b/src/ILCompiler.MetadataTransform/tests/SampleWinRTMetadataAssembly/SampleWinRTMetadataAssembly.csproj
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <OutputType>Library</OutputType>
+ <AssemblyName>SampleWinRTMetadataAssembly</AssemblyName>
+ <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+ <ProjectGuid>{46CDD663-FCCC-4E74-901F-3D9D5A36A0D9}</ProjectGuid>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\PrimaryMetadataAssembly\PrimaryMetadataAssembly.csproj" />
+ <ProjectReference Include="..\SampleMetadataAssembly\SampleMetadataAssembly.csproj" />
+ <ProjectReference Include="..\WindowsWinrtMetadataAssembly\WindowsWinrtMetadataAssembly.csproj" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="SampleWinRTMetadata.cs" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/ILCompiler.MetadataTransform/tests/SingleFileMetadataPolicy.cs b/src/ILCompiler.MetadataTransform/tests/SingleFileMetadataPolicy.cs
index 049176cbc..c8fab721e 100644
--- a/src/ILCompiler.MetadataTransform/tests/SingleFileMetadataPolicy.cs
+++ b/src/ILCompiler.MetadataTransform/tests/SingleFileMetadataPolicy.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Reflection;
using ILCompiler.Metadata;
using Internal.TypeSystem;
@@ -10,6 +11,9 @@ namespace MetadataTransformTests
{
struct SingleFileMetadataPolicy : IMetadataPolicy
{
+ private static object s_lazyInitThreadSafetyLock = new object();
+ private ExplicitScopeAssemblyPolicyMixin _explicitScopePolicyMixin;
+
public bool GeneratesMetadata(MethodDesc methodDef)
{
return true;
@@ -35,5 +39,19 @@ namespace MetadataTransformTests
return false;
}
+
+ public ModuleDesc GetModuleOfType(MetadataType typeDef)
+ {
+ if (_explicitScopePolicyMixin == null)
+ {
+ lock (s_lazyInitThreadSafetyLock)
+ {
+ if (_explicitScopePolicyMixin == null)
+ _explicitScopePolicyMixin = new ExplicitScopeAssemblyPolicyMixin();
+ }
+ }
+
+ return _explicitScopePolicyMixin.GetModuleOfType(typeDef);
+ }
}
}
diff --git a/src/ILCompiler.MetadataTransform/tests/TestTypeSystemContext.cs b/src/ILCompiler.MetadataTransform/tests/TestTypeSystemContext.cs
index 850b4415a..6ae9dbf81 100644
--- a/src/ILCompiler.MetadataTransform/tests/TestTypeSystemContext.cs
+++ b/src/ILCompiler.MetadataTransform/tests/TestTypeSystemContext.cs
@@ -18,25 +18,40 @@ namespace MetadataTransformTests
{
Dictionary<string, EcmaModule> _modules = new Dictionary<string, EcmaModule>(StringComparer.OrdinalIgnoreCase);
- public EcmaModule GetModuleForSimpleName(string simpleName)
+ public EcmaModule GetModuleForSimpleName(string simpleName, bool throwIfNotFound = true)
{
- EcmaModule existingModule;
- if (_modules.TryGetValue(simpleName, out existingModule))
- return existingModule;
-
- return CreateModuleForSimpleName(simpleName);
+ EcmaModule module;
+ if (!_modules.TryGetValue(simpleName, out module))
+ {
+ module = CreateModuleForSimpleName(simpleName);
+ }
+
+ if (module == null && throwIfNotFound)
+ {
+ throw new FileNotFoundException(simpleName + ".dll");
+ }
+ return module;
}
public EcmaModule CreateModuleForSimpleName(string simpleName)
{
- EcmaModule module = EcmaModule.Create(this, new PEReader(File.OpenRead(simpleName + ".dll")));
+ EcmaModule module = null;
+ try
+ {
+ module = EcmaModule.Create(this, new PEReader(File.OpenRead(simpleName + ".dll")));
+ }
+ catch (FileNotFoundException)
+ {
+ // FileNotFound is treated as being unable to load the module
+ }
+
_modules.Add(simpleName, module);
return module;
}
public override ModuleDesc ResolveAssembly(System.Reflection.AssemblyName name, bool throwIfNotFound)
{
- return GetModuleForSimpleName(name.Name);
+ return GetModuleForSimpleName(name.Name, throwIfNotFound);
}
}
}
diff --git a/src/ILCompiler.MetadataTransform/tests/WindowsWinrtMetadataAssembly/WindowsWinrtMetadata.cs b/src/ILCompiler.MetadataTransform/tests/WindowsWinrtMetadataAssembly/WindowsWinrtMetadata.cs
new file mode 100644
index 000000000..471ffbaa4
--- /dev/null
+++ b/src/ILCompiler.MetadataTransform/tests/WindowsWinrtMetadataAssembly/WindowsWinrtMetadata.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+#pragma warning disable 414
+#pragma warning disable 67
+#pragma warning disable 3009
+#pragma warning disable 3016
+#pragma warning disable 3001
+#pragma warning disable 3015
+#pragma warning disable 169
+#pragma warning disable 649
+
+namespace Windows
+{
+ [Internal.Reflection.ExplicitScope("Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime")]
+ public class Control
+ {
+ }
+}
diff --git a/src/ILCompiler.MetadataTransform/tests/WindowsWinrtMetadataAssembly/WindowsWinrtMetadataAssembly.csproj b/src/ILCompiler.MetadataTransform/tests/WindowsWinrtMetadataAssembly/WindowsWinrtMetadataAssembly.csproj
new file mode 100644
index 000000000..19a4d2875
--- /dev/null
+++ b/src/ILCompiler.MetadataTransform/tests/WindowsWinrtMetadataAssembly/WindowsWinrtMetadataAssembly.csproj
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <OutputType>Library</OutputType>
+ <AssemblyName>WindowsWinrtMetadataAssembly</AssemblyName>
+ <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+ <ProjectGuid>{19D0BAA8-8762-4D64-80AF-53D7A2BBC4AE}</ProjectGuid>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\PrimaryMetadataAssembly\PrimaryMetadataAssembly.csproj" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="WindowsWinrtMetadata.cs" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file