From 3afb2e2423908129dea5a06435e53a844b0e34be Mon Sep 17 00:00:00 2001 From: n9 Date: Thu, 11 Dec 2014 15:06:46 +0100 Subject: [PATCH 1/2] DefaultMemberReflectabilityAttribute added Inheritable option --- .../Saltarelle.Compiler/AttributeStore.cs | 67 ++++++++++--------- .../Driver/CompilerDriver.cs | 16 ++++- .../Saltarelle.Compiler/IMetadataImporter.cs | 11 +-- Runtime/CoreLib.Plugin/CoreLib.Plugin.csproj | 1 + .../InheritDefaultMemberReflectability.cs | 51 ++++++++++++++ .../Reflection/ReflectionTests.cs | 31 +++++++++ Runtime/CoreLib/ScriptMetadata.cs | 1 + 7 files changed, 135 insertions(+), 43 deletions(-) create mode 100644 Runtime/CoreLib.Plugin/InheritDefaultMemberReflectability.cs diff --git a/Compiler/Saltarelle.Compiler/AttributeStore.cs b/Compiler/Saltarelle.Compiler/AttributeStore.cs index 960ac9ff..a3cca143 100644 --- a/Compiler/Saltarelle.Compiler/AttributeStore.cs +++ b/Compiler/Saltarelle.Compiler/AttributeStore.cs @@ -16,58 +16,63 @@ public class AttributeStore : IAttributeStore { private readonly IErrorReporter _errorReporter; private readonly Dictionary _assemblyStore; private readonly Dictionary _entityStore; - private readonly List> _assemblyTransformers; - private readonly List> _entityTransformers; public AttributeStore(ICompilation compilation, IErrorReporter errorReporter) { _errorReporter = errorReporter; _assemblyStore = new Dictionary(); _entityStore = new Dictionary(); - _assemblyTransformers = new List>(); - _entityTransformers = new List>(); foreach (var a in compilation.Assemblies) { - ReadAssemblyAttributes(a, _assemblyTransformers); + ReadAssemblyAttributes(a); } foreach (var t in compilation.Assemblies.SelectMany(a => TreeTraversal.PostOrder(a.TopLevelTypeDefinitions, t => t.NestedTypes))) { foreach (var m in t.Methods) { - ReadEntityAttributes(m, _entityTransformers); + ReadEntityAttributes(m); } foreach (var p in t.Properties) { if (p.CanGet) - ReadEntityAttributes(p.Getter, _entityTransformers); + ReadEntityAttributes(p.Getter); if (p.CanSet) - ReadEntityAttributes(p.Setter, _entityTransformers); - ReadEntityAttributes(p, _entityTransformers); + ReadEntityAttributes(p.Setter); + ReadEntityAttributes(p); } foreach (var f in t.Fields) { - ReadEntityAttributes(f, _entityTransformers); + ReadEntityAttributes(f); } foreach (var e in t.Events) { if (e.CanAdd) - ReadEntityAttributes(e.AddAccessor, _entityTransformers); + ReadEntityAttributes(e.AddAccessor); if (e.CanRemove) - ReadEntityAttributes(e.RemoveAccessor, _entityTransformers); - ReadEntityAttributes(e, _entityTransformers); + ReadEntityAttributes(e.RemoveAccessor); + ReadEntityAttributes(e); } - ReadEntityAttributes(t, _entityTransformers); + ReadEntityAttributes(t); } } public void RunAttributeCode() { - foreach (var t in _entityTransformers) { - _errorReporter.Region = t.Item1.Region; - t.Item2.ApplyTo(t.Item1, this, _errorReporter); + foreach (var p in _entityStore) + { + _errorReporter.Region = p.Key.Region; + foreach (var a in p.Value) + { + var pab = a as PluginAttributeBase; + if (pab != null) + pab.ApplyTo(p.Key, this, _errorReporter); + } } _errorReporter.Region = default(DomRegion); - foreach (var t in _assemblyTransformers) { - t.Item2.ApplyTo(t.Item1, this, _errorReporter); - } - - _entityTransformers.Clear(); - _assemblyTransformers.Clear(); + foreach (var p in _assemblyStore) + { + foreach (var a in p.Value) + { + var pab = a as PluginAttributeBase; + if (pab != null) + pab.ApplyTo(p.Key, this, _errorReporter); + } + } } public AttributeList AttributesFor(IAssembly assembly) { @@ -82,25 +87,21 @@ public AttributeList AttributesFor(IEntity entity) { return result; } - private void ReadAssemblyAttributes(IAssembly assembly, List> transformers) { - _assemblyStore[assembly] = ReadAttributes(assembly, assembly.AssemblyAttributes, transformers); + private void ReadAssemblyAttributes(IAssembly assembly) { + _assemblyStore[assembly] = ReadAttributes(assembly, assembly.AssemblyAttributes); } - private void ReadEntityAttributes(IEntity entity, List> transformers) { - _entityStore[entity] = ReadAttributes(entity, entity.Attributes, transformers); + private void ReadEntityAttributes(IEntity entity) { + _entityStore[entity] = ReadAttributes(entity, entity.Attributes); } - private AttributeList ReadAttributes(T t, IEnumerable attributes, List> transformers) { + private AttributeList ReadAttributes(T t, IEnumerable attributes) { var l = new AttributeList(); foreach (var a in attributes) { var type = FindType(a.AttributeType); if (type != null) { var attr = ReadAttribute(a, type); - var pab = attr as PluginAttributeBase; - l.Add(attr); - if (pab != null) { - transformers.Add(Tuple.Create(t, pab)); - } + l.Add(attr); } } return l; diff --git a/Compiler/Saltarelle.Compiler/Driver/CompilerDriver.cs b/Compiler/Saltarelle.Compiler/Driver/CompilerDriver.cs index bf7ee63c..6c65723a 100644 --- a/Compiler/Saltarelle.Compiler/Driver/CompilerDriver.cs +++ b/Compiler/Saltarelle.Compiler/Driver/CompilerDriver.cs @@ -238,9 +238,23 @@ private static IEnumerable LoadResources(IEnumerable new Resource(r.ResourceName, r.Filename, r.IsPublic)); } + private static IEnumerable GetBaseAndOuterTypeDefinitions(ICSharpCode.NRefactory.TypeSystem.ITypeDefinition t) + { + foreach (var b in t.DirectBaseTypes) + yield return b.GetDefinition(); + if (t.DeclaringTypeDefinition != null) + yield return t.DeclaringTypeDefinition; + } + + public static IEnumerable SortTypes(IEnumerable types) + { + var l = types.ToList(); + return TopologicalSorter.TopologicalSort(l, l.SelectMany(GetBaseAndOuterTypeDefinitions, Edge.Create)); + } + private void InitializeAttributeStore(AttributeStore attributeStore, WindsorContainer container, ICompilation compilation) { var assemblies = compilation.Assemblies; - var types = compilation.GetAllTypeDefinitions().ToList(); + var types = SortTypes(compilation.GetAllTypeDefinitions()).ToList(); foreach (var applier in container.ResolveAll()) { foreach (var a in assemblies) applier.Process(a); diff --git a/Compiler/Saltarelle.Compiler/IMetadataImporter.cs b/Compiler/Saltarelle.Compiler/IMetadataImporter.cs index bd38413f..4187fa11 100644 --- a/Compiler/Saltarelle.Compiler/IMetadataImporter.cs +++ b/Compiler/Saltarelle.Compiler/IMetadataImporter.cs @@ -7,6 +7,7 @@ using Saltarelle.Compiler.JSModel.TypeSystem; using Saltarelle.Compiler.ScriptSemantics; using TopologicalSort; +using Saltarelle.Compiler.Driver; namespace Saltarelle.Compiler { public interface IMetadataImporter { @@ -116,16 +117,8 @@ public interface IMetadataImporter { } public static class MetadataImporterExtensions { - private static IEnumerable GetBaseAndOuterTypeDefinitions(ITypeDefinition t) { - foreach (var b in t.DirectBaseTypes) - yield return b.GetDefinition(); - if (t.DeclaringTypeDefinition != null) - yield return t.DeclaringTypeDefinition; - } - public static void Prepare(this IMetadataImporter md, IEnumerable types) { - var l = types.ToList(); - foreach (var t in TopologicalSorter.TopologicalSort(l, l.SelectMany(GetBaseAndOuterTypeDefinitions, Edge.Create))) + foreach (var t in CompilerDriver.SortTypes(types)) md.Prepare(t); } } diff --git a/Runtime/CoreLib.Plugin/CoreLib.Plugin.csproj b/Runtime/CoreLib.Plugin/CoreLib.Plugin.csproj index 8f75e233..6fb5918c 100644 --- a/Runtime/CoreLib.Plugin/CoreLib.Plugin.csproj +++ b/Runtime/CoreLib.Plugin/CoreLib.Plugin.csproj @@ -61,6 +61,7 @@ ScriptMetadata.cs + diff --git a/Runtime/CoreLib.Plugin/InheritDefaultMemberReflectability.cs b/Runtime/CoreLib.Plugin/InheritDefaultMemberReflectability.cs new file mode 100644 index 00000000..f30e80b1 --- /dev/null +++ b/Runtime/CoreLib.Plugin/InheritDefaultMemberReflectability.cs @@ -0,0 +1,51 @@ +using ICSharpCode.NRefactory.TypeSystem; +using Saltarelle.Compiler; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; + +namespace CoreLib.Plugin +{ + public class InheritDefaultMemberReflectability : IAutomaticMetadataAttributeApplier + { + private readonly IAttributeStore _attributeStore; + + public InheritDefaultMemberReflectability(IAttributeStore attributeStore) + { + _attributeStore = attributeStore; + } + + public void Process(ITypeDefinition type) + { + var attributes = _attributeStore.AttributesFor(type); + if (attributes.HasAttribute()) + return; + var intReflectability = (int)MemberReflectability.None; + foreach (var bt in type.DirectBaseTypes) + { + var btd = bt as ITypeDefinition; + if (btd == null) + continue; + var attribute = _attributeStore.AttributesFor(btd).GetAttribute(); + if (attribute == null || !attribute.Inheritable) + continue; + intReflectability = Math.Max(intReflectability, (int)attribute.DefaultReflectability); + } + var reflectability = (MemberReflectability)intReflectability; + if (reflectability == MemberReflectability.None) + return; + var a = new DefaultMemberReflectabilityAttribute(reflectability) + { + Inheritable = true + }; + attributes.Add(a); + } + + public void Process(IAssembly assembly) + { + + } + } +} diff --git a/Runtime/CoreLib.TestScript/Reflection/ReflectionTests.cs b/Runtime/CoreLib.TestScript/Reflection/ReflectionTests.cs index 1ebc124f..e6e2fe70 100644 --- a/Runtime/CoreLib.TestScript/Reflection/ReflectionTests.cs +++ b/Runtime/CoreLib.TestScript/Reflection/ReflectionTests.cs @@ -347,6 +347,22 @@ public class C28 { [Reflectable(false)] private int D5; } + [DefaultMemberReflectability(MemberReflectability.All, Inheritable = true)] + public class C29 + { + public int A1; + } + + public class C30 : C29 + { + public int A2; + } + + public class C31 : C30 + { + public int A3; + } + [Test] public void GetMembersReturnsMethodsWithAnyScriptableAttributeOrReflectableAttribute() { var methods = typeof(C1).GetMembers(); @@ -1632,5 +1648,20 @@ public void MembersReflectableAttributeWorks() { Assert.IsNotNull(c28.GetField("C5"), "C28.C5"); Assert.IsNull (c28.GetField("D5"), "C28.D5"); } + + [Test] + public void MembersReflectableAttributeInheritableWorks() + { + var c29 = typeof(C29); + var c30 = typeof(C30); + var c31 = typeof(C31); + + Assert.IsNotNull(c29.GetField("A1"), "C29.A1"); + Assert.IsNotNull(c30.GetField("A1", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy), "C30.A1"); + Assert.IsNotNull(c30.GetField("A2"), "C30.A2"); + Assert.IsNotNull(c31.GetField("A1", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy), "C31.A1"); + Assert.IsNotNull(c31.GetField("A2", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy), "C31.A2"); + Assert.IsNotNull(c31.GetField("A3"), "C30.A3"); + } } } diff --git a/Runtime/CoreLib/ScriptMetadata.cs b/Runtime/CoreLib/ScriptMetadata.cs index b8f21bd8..d20f3ce0 100644 --- a/Runtime/CoreLib/ScriptMetadata.cs +++ b/Runtime/CoreLib/ScriptMetadata.cs @@ -511,6 +511,7 @@ public sealed partial class DefaultMemberReflectabilityAttribute : #endif { public MemberReflectability DefaultReflectability { get; private set; } + public bool Inheritable { get; set; } public DefaultMemberReflectabilityAttribute(MemberReflectability defaultReflectability) { DefaultReflectability = defaultReflectability; From 75c88d029e957bc20572f068d23225aa55c3d3fc Mon Sep 17 00:00:00 2001 From: n9 Date: Tue, 16 Dec 2014 17:36:38 +0100 Subject: [PATCH 2/2] fixed InheritDefaultMemberReflectability for generic types --- .../InheritDefaultMemberReflectability.cs | 4 +--- .../Reflection/ReflectionTests.cs | 23 ++++++++++++++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Runtime/CoreLib.Plugin/InheritDefaultMemberReflectability.cs b/Runtime/CoreLib.Plugin/InheritDefaultMemberReflectability.cs index f30e80b1..7fc9ceeb 100644 --- a/Runtime/CoreLib.Plugin/InheritDefaultMemberReflectability.cs +++ b/Runtime/CoreLib.Plugin/InheritDefaultMemberReflectability.cs @@ -25,9 +25,7 @@ public void Process(ITypeDefinition type) var intReflectability = (int)MemberReflectability.None; foreach (var bt in type.DirectBaseTypes) { - var btd = bt as ITypeDefinition; - if (btd == null) - continue; + var btd = bt.GetDefinition(); var attribute = _attributeStore.AttributesFor(btd).GetAttribute(); if (attribute == null || !attribute.Inheritable) continue; diff --git a/Runtime/CoreLib.TestScript/Reflection/ReflectionTests.cs b/Runtime/CoreLib.TestScript/Reflection/ReflectionTests.cs index e6e2fe70..c96764fa 100644 --- a/Runtime/CoreLib.TestScript/Reflection/ReflectionTests.cs +++ b/Runtime/CoreLib.TestScript/Reflection/ReflectionTests.cs @@ -363,6 +363,16 @@ public class C31 : C30 public int A3; } + public class C32 : C29 + { + public int A4; + } + + public class C33 : C32 + { + public int A5; + } + [Test] public void GetMembersReturnsMethodsWithAnyScriptableAttributeOrReflectableAttribute() { var methods = typeof(C1).GetMembers(); @@ -1655,13 +1665,24 @@ public void MembersReflectableAttributeInheritableWorks() var c29 = typeof(C29); var c30 = typeof(C30); var c31 = typeof(C31); + var c32 = typeof(C32); + var c33 = typeof(C33); Assert.IsNotNull(c29.GetField("A1"), "C29.A1"); + Assert.IsNotNull(c30.GetField("A1", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy), "C30.A1"); Assert.IsNotNull(c30.GetField("A2"), "C30.A2"); + Assert.IsNotNull(c31.GetField("A1", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy), "C31.A1"); Assert.IsNotNull(c31.GetField("A2", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy), "C31.A2"); - Assert.IsNotNull(c31.GetField("A3"), "C30.A3"); + Assert.IsNotNull(c31.GetField("A3"), "C31.A3"); + + Assert.IsNotNull(c32.GetField("A1", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy), "C32.A1"); + Assert.IsNotNull(c32.GetField("A4"), "C32.A4"); + + Assert.IsNotNull(c33.GetField("A1", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy), "C33.A1"); + Assert.IsNotNull(c33.GetField("A4", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy), "C33.A4"); + Assert.IsNotNull(c33.GetField("A5"), "C33.A5"); } } }