From 5baadf1bd18381aedfeb8b659a2916ba31384f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Wed, 12 Feb 2020 14:34:41 +0000 Subject: [PATCH] Several fixes with minimization workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix bug with checking of attributes to exclude. - Expose IgnoringAttributes collection. - Add extension to check typered against attributes list. - Several improvements in MemberRef and Field tokens processing. Signed-off-by: José Simões --- .../Extensions/TypeReferenceExtensions.cs | 17 ++ .../MetadataProcessor.Core.csproj | 1 + .../Tables/nanoTablesContext.cs | 21 +- .../nanoAssemblyBuilder.cs | 215 ++++++++++++++---- 4 files changed, 206 insertions(+), 48 deletions(-) create mode 100644 source/MetadataProcessor.Core/Extensions/TypeReferenceExtensions.cs diff --git a/source/MetadataProcessor.Core/Extensions/TypeReferenceExtensions.cs b/source/MetadataProcessor.Core/Extensions/TypeReferenceExtensions.cs new file mode 100644 index 00000000..4a1e6fe5 --- /dev/null +++ b/source/MetadataProcessor.Core/Extensions/TypeReferenceExtensions.cs @@ -0,0 +1,17 @@ +// +// Copyright (c) 2019 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +using Mono.Cecil; + +namespace nanoFramework.Tools.MetadataProcessor.Core.Extensions +{ + internal static class TypeReferenceExtensions + { + public static bool IsToInclude(this TypeReference value) + { + return !nanoTablesContext.IgnoringAttributes.Contains(value.FullName); + } + } +} diff --git a/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj b/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj index d6f919bd..d461e122 100644 --- a/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj +++ b/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj @@ -95,6 +95,7 @@ + diff --git a/source/MetadataProcessor.Core/Tables/nanoTablesContext.cs b/source/MetadataProcessor.Core/Tables/nanoTablesContext.cs index a2f96a7e..40854e88 100644 --- a/source/MetadataProcessor.Core/Tables/nanoTablesContext.cs +++ b/source/MetadataProcessor.Core/Tables/nanoTablesContext.cs @@ -13,10 +13,10 @@ namespace nanoFramework.Tools.MetadataProcessor { public sealed class nanoTablesContext { - private readonly HashSet _ignoringAttributes = - new HashSet(StringComparer.Ordinal) + internal static HashSet IgnoringAttributes { get; } = new HashSet(StringComparer.Ordinal) { // Assembly-level attributes + "System.Reflection.AssemblyFileVersionAttribute", "System.Runtime.InteropServices.ComVisibleAttribute", "System.Runtime.InteropServices.GuidAttribute", @@ -53,6 +53,9 @@ public sealed class nanoTablesContext // Intellisense filtering attributes "System.ComponentModel.EditorBrowsableAttribute", + //Not supported + "System.Reflection.DefaultMemberAttribute", + // Not supported attributes "System.MTAThreadAttribute", "System.STAThreadAttribute", @@ -77,19 +80,19 @@ public nanoTablesContext( // add it to ignore list, if it's not already there if ((ClassNamesToExclude.Contains(item.AttributeType.FullName) || ClassNamesToExclude.Contains(item.AttributeType.DeclaringType?.FullName)) && - !(_ignoringAttributes.Contains(item.AttributeType.FullName) || - _ignoringAttributes.Contains(item.AttributeType.DeclaringType?.FullName))) + !(IgnoringAttributes.Contains(item.AttributeType.FullName) || + IgnoringAttributes.Contains(item.AttributeType.DeclaringType?.FullName))) { - _ignoringAttributes.Add(item.AttributeType.FullName); + IgnoringAttributes.Add(item.AttributeType.FullName); } } // check ignoring attributes against ClassNamesToExclude foreach(var className in ClassNamesToExclude) { - if(!_ignoringAttributes.Contains(className)) + if(!IgnoringAttributes.Contains(className)) { - _ignoringAttributes.Add(className); + IgnoringAttributes.Add(className); } } @@ -266,8 +269,8 @@ private bool IsAttribute( MemberReference typeReference) { return - (_ignoringAttributes.Contains(typeReference.FullName) || - _ignoringAttributes.Contains(typeReference.DeclaringType?.FullName)); + (IgnoringAttributes.Contains(typeReference.FullName) || + IgnoringAttributes.Contains(typeReference.DeclaringType?.FullName)); } private static List GetOrderedTypes( diff --git a/source/MetadataProcessor.Core/nanoAssemblyBuilder.cs b/source/MetadataProcessor.Core/nanoAssemblyBuilder.cs index 6a0ec42d..a637b0f1 100644 --- a/source/MetadataProcessor.Core/nanoAssemblyBuilder.cs +++ b/source/MetadataProcessor.Core/nanoAssemblyBuilder.cs @@ -5,9 +5,11 @@ // using Mono.Cecil; +using Mono.Collections.Generic; using nanoFramework.Tools.MetadataProcessor.Core.Extensions; using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Text; @@ -278,11 +280,22 @@ private HashSet BuildDependencyList(MetadataToken token) break; case TokenType.MemberRef: + + Collection parameters = null; + + // try to find a method reference var mr = _tablesContext.MethodReferencesTable.Items.FirstOrDefault(i => i.MetadataToken == token); if (mr != null && mr.ReturnType != null) { + parameters = mr.Parameters; + + if (mr.DeclaringType != null) + { + set.Add(mr.DeclaringType.MetadataToken); + } + if (mr.MethodReturnType.ReturnType.IsValueType && !mr.MethodReturnType.ReturnType.IsPrimitive) { @@ -294,34 +307,88 @@ private HashSet BuildDependencyList(MetadataToken token) { set.Add(mr.ReturnType.DeclaringType.MetadataToken); } + else + { + set.Add(mr.DeclaringType.MetadataToken); + } } - else if (mr.ReturnType.FullName != "System.Void" && - mr.ReturnType.FullName != "System.String" && - !mr.MethodReturnType.ReturnType.IsPrimitive) + else { - set.Add(mr.ReturnType.MetadataToken); + if (mr.ReturnType.MetadataType == MetadataType.ValueType) + { + if (mr.ReturnType.FullName != "System.Void" && + mr.ReturnType.FullName != "System.String" && + mr.ReturnType.FullName != "System.Object" && + !mr.ReturnType.IsPrimitive) + { + set.Add(mr.ReturnType.MetadataToken); + } + } + if (mr.ReturnType.MetadataType == MetadataType.Class) + { + set.Add(mr.ReturnType.MetadataToken); + } } - else if(mr.DeclaringType != null) + + // parameters + foreach (var p in mr.Parameters) { - set.Add(mr.DeclaringType.MetadataToken); + if (p.ParameterType.DeclaringType != null) + { + set.Add(p.ParameterType.DeclaringType.MetadataToken); + } + else if (p.ParameterType.MetadataType == MetadataType.Class) + { + set.Add(p.ParameterType.MetadataToken); + } + else if (p.ParameterType.IsValueType && + !p.ParameterType.IsPrimitive) + { + set.Add(p.ParameterType.MetadataToken); + } } } - // parameters - foreach (var p in mr.Parameters) + if (mr == null) { - if (p.ParameterType.DeclaringType != null) - { - set.Add(p.ParameterType.DeclaringType.MetadataToken); - } - else if (p.ParameterType.MetadataType == MetadataType.Class) - { - set.Add(p.ParameterType.MetadataToken); - } - else if (p.ParameterType.IsValueType && - !p.ParameterType.IsPrimitive) + // try now with field references + var fr = _tablesContext.FieldReferencesTable.Items.FirstOrDefault(i => i.MetadataToken == token); + + if (fr != null) { - set.Add(p.ParameterType.MetadataToken); + if (fr.DeclaringType != null) + { + set.Add(fr.DeclaringType.MetadataToken); + } + + if (fr.FieldType.IsValueType && + !fr.FieldType.IsPrimitive) + { + set.Add(fr.FieldType.MetadataToken); + } + else if (fr.FieldType.IsArray) + { + if (fr.FieldType.DeclaringType != null) + { + set.Add(fr.FieldType.MetadataToken); + } + else + { + set.Add(fr.DeclaringType.MetadataToken); + } + } + else if (fr.FieldType.FullName != "System.Void" && + fr.FieldType.FullName != "System.String" && + fr.FieldType.FullName != "System.Object" && + fr.FieldType.IsValueType && + !fr.FieldType.IsPrimitive) + { + set.Add(fr.FieldType.MetadataToken); + } + else if (fr.FieldType.DeclaringType != null) + { + set.Add(fr.FieldType.DeclaringType.MetadataToken); + } } } @@ -353,7 +420,8 @@ private HashSet BuildDependencyList(MetadataToken token) // include attributes foreach(var c in td.CustomAttributes) { - if (!nanoTablesContext.ClassNamesToExclude.Contains(c.AttributeType.FullName)) + if (!nanoTablesContext.ClassNamesToExclude.Contains(c.AttributeType.FullName) && + c.AttributeType.IsToInclude()) { set.Add(c.AttributeType.MetadataToken); } @@ -402,8 +470,22 @@ private HashSet BuildDependencyList(MetadataToken token) { set.Add(fd.FieldType.MetadataToken); } + else if (fd.FieldType.IsArray) + { + if (fd.FieldType.DeclaringType != null) + { + set.Add(fd.FieldType.DeclaringType.MetadataToken); + } + else + { + set.Add(fd.DeclaringType.MetadataToken); + } + } else if (!fd.FieldType.IsValueType && - !fd.FieldType.IsPrimitive) + !fd.FieldType.IsPrimitive && + fd.FieldType.FullName != "System.Void" && + fd.FieldType.FullName != "System.String" && + fd.FieldType.FullName != "System.Object") { set.Add(fd.FieldType.MetadataToken); } @@ -411,7 +493,8 @@ private HashSet BuildDependencyList(MetadataToken token) // attributes foreach (var c in fd.CustomAttributes) { - if (!nanoTablesContext.ClassNamesToExclude.Contains(c.AttributeType.FullName)) + if (!nanoTablesContext.ClassNamesToExclude.Contains(c.AttributeType.FullName) && + c.AttributeType.IsToInclude()) { set.Add(c.Constructor.MetadataToken); } @@ -423,29 +506,57 @@ private HashSet BuildDependencyList(MetadataToken token) var md = _tablesContext.MethodDefinitionTable.Items.FirstOrDefault(i => i.MetadataToken == token); // return value - if( md.ReturnType.FullName != "System.Void" && - md.ReturnType.FullName != "System.String" && - !md.ReturnType.IsArray && - !md.ReturnType.IsPrimitive) + if (md.ReturnType.IsValueType && + !md.ReturnType.IsPrimitive) + { + set.Add(md.ReturnType.MetadataToken); + } + else if (md.ReturnType.IsArray) + { + if (md.ReturnType.DeclaringType != null) + { + set.Add(md.ReturnType.DeclaringType.MetadataToken); + } + else + { + set.Add(md.DeclaringType.MetadataToken); + } + } + else if (!md.ReturnType.IsValueType && + !md.ReturnType.IsPrimitive && + md.ReturnType.FullName != "System.Void" && + md.ReturnType.FullName != "System.String" && + md.ReturnType.FullName != "System.Object") { set.Add(md.ReturnType.MetadataToken); } // parameters - foreach(var p in md.Parameters) + foreach (var p in md.Parameters) { - if (p.ParameterType.DeclaringType != null) + TypeReference parameterType = null; + + if (p.ParameterType is ByReferenceType byReference) { - set.Add(p.ParameterType.DeclaringType.MetadataToken); + parameterType = byReference.ElementType; } - else if (p.ParameterType.MetadataType == MetadataType.Class) + else { - set.Add(p.ParameterType.MetadataToken); + parameterType = p.ParameterType; } - else if (p.ParameterType.IsValueType && - !p.ParameterType.IsPrimitive) + + if (parameterType.DeclaringType != null) + { + set.Add(parameterType.DeclaringType.MetadataToken); + } + else if (parameterType.MetadataType == MetadataType.Class) + { + set.Add(parameterType.MetadataToken); + } + else if (parameterType.IsValueType && + !parameterType.IsPrimitive) { - set.Add(p.ParameterType.MetadataToken); + set.Add(parameterType.MetadataToken); } } @@ -480,7 +591,7 @@ i.Operand is TypeSpecification || { set.Add(((IMetadataTokenProvider)i.Operand).MetadataToken); } - else if (i.Operand is String) + else if (i.Operand is string) { var stringId = _tablesContext.StringTable.GetOrCreateStringId((string)i.Operand); @@ -504,7 +615,8 @@ i.Operand is TypeSpecification || // attributes foreach (var c in md.CustomAttributes) { - if (!nanoTablesContext.ClassNamesToExclude.Contains(c.AttributeType.FullName)) + if (!nanoTablesContext.ClassNamesToExclude.Contains(c.AttributeType.FullName) && + c.AttributeType.IsToInclude()) { set.Add(c.Constructor.MetadataToken); } @@ -622,15 +734,40 @@ private string TokenToString(MetadataToken token) break; case TokenType.MemberRef: + + TypeReference typeRef = null; + string typeName = string.Empty; + + // try to find a method reference var mr = _tablesContext.MethodReferencesTable.Items.FirstOrDefault(i => i.MetadataToken == token); - if (mr.DeclaringType != null) + if (mr != null) + { + typeRef = mr.DeclaringType; + typeName = mr.Name; + } + else + { + // try now with field references + var fr = _tablesContext.FieldReferencesTable.Items.FirstOrDefault(i => i.MetadataToken == token); + + if (fr != null) + { + typeRef = fr.DeclaringType; + typeName = fr.Name; + } + } + + Debug.Assert(typeRef != null); + Debug.Assert(typeName != string.Empty); + + if (typeRef != null) { - output.Append(TokenToString(mr.DeclaringType.MetadataToken)); + output.Append(TokenToString(typeRef.MetadataToken)); output.Append("::"); } - output.Append(mr.Name); + output.Append(typeName); break; case TokenType.ModuleRef: