From 27e9ca33cc9077e062e3411467b955f69352bc2e Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 29 Sep 2019 22:04:28 -0700 Subject: [PATCH 01/13] Report a build error if 'AnnotatedReferenceAssemblyVersion' is not defined --- .../TunnelVisionLabs.ReferenceAssemblyAnnotator.targets | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/TunnelVisionLabs.ReferenceAssemblyAnnotator.targets b/TunnelVisionLabs.ReferenceAssemblyAnnotator/TunnelVisionLabs.ReferenceAssemblyAnnotator.targets index 487b240..fa497a0 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/TunnelVisionLabs.ReferenceAssemblyAnnotator.targets +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/TunnelVisionLabs.ReferenceAssemblyAnnotator.targets @@ -55,6 +55,8 @@ Inputs="@(AvailableUnannotatedReferenceAssembly);@(AnnotatedReferenceAssembly)" Outputs="@(UnannotatedReferenceAssembly->'%(OutputAssembly)')"> + + Date: Sun, 29 Sep 2019 22:05:21 -0700 Subject: [PATCH 02/13] Ensure the rewritten assembly is marked with ReferenceAssemblyAttribute --- .../CustomAttributeFactory.cs | 7 +++++++ .../Program.cs | 18 ++++++++++++++++++ .../WellKnownTypes.cs | 3 +++ 3 files changed, 28 insertions(+) diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/CustomAttributeFactory.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/CustomAttributeFactory.cs index 7a4e700..c5a1771 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/CustomAttributeFactory.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/CustomAttributeFactory.cs @@ -76,5 +76,12 @@ public CustomAttribute AttributeUsage(AttributeTargets validOn, bool? allowMulti return customAttribute; } + + public CustomAttribute ReferenceAssembly() + { + MethodDefinition constructor = _wellKnownTypes.SystemRuntimeCompilerServicesReferenceAssemblyAttribute.Resolve().Methods.Single(method => method.IsConstructor && !method.IsStatic && method.Parameters.Count == 0); + var customAttribute = new CustomAttribute(_wellKnownTypes.Module.ImportReference(constructor)); + return customAttribute; + } } } diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs index 41051b7..e4d6e7e 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs @@ -7,6 +7,7 @@ namespace TunnelVisionLabs.ReferenceAssemblyAnnotator using System.Collections.Generic; using System.IO; using System.Linq; + using System.Runtime.CompilerServices; using Microsoft.Build.Utilities; using Mono.Cecil; using Mono.Cecil.Rocks; @@ -44,6 +45,9 @@ internal static void Main(TaskLoggingHelper? log, string referenceAssembly, stri var notNullIfNotNullAttribute = DefineNotNullIfNotNullAttribute(assemblyDefinition, wellKnownTypes, attributeFactory); var notNullWhenAttribute = DefineNotNullWhenAttribute(assemblyDefinition, wellKnownTypes, attributeFactory); + // Ensure the assembly is marked with ReferenceAssemblyAttribute + EnsureReferenceAssemblyAttribute(assemblyDefinition, wellKnownTypes, attributeFactory); + var attributesOfInterest = new Dictionary(); attributesOfInterest.Add(nullableAttribute.FullName, nullableAttribute); attributesOfInterest.Add(nullableContextAttribute.FullName, nullableContextAttribute); @@ -506,5 +510,19 @@ private static TypeDefinition DefineNotNullWhenAttribute(AssemblyDefinition asse return attribute; } + + private static void EnsureReferenceAssemblyAttribute(AssemblyDefinition assemblyDefinition, WellKnownTypes wellKnownTypes, CustomAttributeFactory attributeFactory) + { + foreach (var attribute in assemblyDefinition.CustomAttributes) + { + if (attribute.AttributeType.FullName == typeof(ReferenceAssemblyAttribute).FullName) + { + return; + } + } + + var customAttribute = attributeFactory.ReferenceAssembly(); + assemblyDefinition.CustomAttributes.Add(customAttribute); + } } } diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs index 48b5dc8..8833695 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs @@ -17,6 +17,7 @@ public WellKnownTypes(ModuleDefinition module) SystemAttributeTargets = ResolveWellKnownType(module, typeof(AttributeTargets)); SystemAttributeUsageAttribute = ResolveWellKnownType(module, typeof(AttributeUsageAttribute)); SystemRuntimeCompilerServicesCompilerGeneratedAttribute = ResolveWellKnownType(module, typeof(CompilerGeneratedAttribute)); + SystemRuntimeCompilerServicesReferenceAssemblyAttribute = ResolveWellKnownType(module, typeof(ReferenceAssemblyAttribute)); } public ModuleDefinition Module { get; } @@ -31,6 +32,8 @@ public WellKnownTypes(ModuleDefinition module) public TypeReference SystemRuntimeCompilerServicesCompilerGeneratedAttribute { get; } + public TypeReference SystemRuntimeCompilerServicesReferenceAssemblyAttribute { get; } + private static TypeDefinition ResolveWellKnownType(ModuleDefinition module, Type type) { return module.TypeSystem.Object.Resolve().Module.GetType(type.FullName); From 814d62bed882c474045a88c78817a1290601039d Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 29 Sep 2019 22:10:30 -0700 Subject: [PATCH 03/13] Skip mixed-mode assemblies with a warning Fixes #29 --- TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs index e4d6e7e..5c7b6df 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs @@ -20,6 +20,15 @@ internal static void Main(TaskLoggingHelper? log, string referenceAssembly, stri assemblyResolver.AddSearchDirectory(Path.GetDirectoryName(referenceAssembly)); using var assemblyDefinition = AssemblyDefinition.ReadAssembly(referenceAssembly, new ReaderParameters(ReadingMode.Immediate) { AssemblyResolver = assemblyResolver }); + foreach (var module in assemblyDefinition.Modules) + { + if (!module.Attributes.HasFlag(ModuleAttributes.ILOnly)) + { + log?.LogWarning(subcategory: null, "RA1000", helpKeyword: null, file: null, lineNumber: 0, columnNumber: 0, endLineNumber: 0, endColumnNumber: 0, "Skipping mixed-mode implementation assembly '{0}'", assemblyDefinition.Name); + return; + } + } + var annotatedAssemblyResolver = new DefaultAssemblyResolver(); annotatedAssemblyResolver.AddSearchDirectory(Path.GetDirectoryName(annotatedReferenceAssembly)); using var annotatedAssemblyDefinition = AssemblyDefinition.ReadAssembly(annotatedReferenceAssembly, new ReaderParameters(ReadingMode.Immediate) { AssemblyResolver = annotatedAssemblyResolver }); From 0d28271efb160a520050eba5afc24824f688757d Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 29 Sep 2019 22:24:33 -0700 Subject: [PATCH 04/13] Annotate implemented interfaces Fixes #28 --- TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs index 5c7b6df..36e1011 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs @@ -106,6 +106,16 @@ private static void AnnotateType(TaskLoggingHelper? log, TypeDefinition typeDefi } Annotate(typeDefinition, annotatedTypeDefinition, attributesOfInterest); + for (var i = 0; i < typeDefinition.Interfaces.Count; i++) + { + for (int j = 0; j < annotatedTypeDefinition.Interfaces.Count; j++) + { + if (EquivalenceComparers.TypeReference.Equals(typeDefinition.Interfaces[i].InterfaceType, annotatedTypeDefinition.Interfaces[j].InterfaceType)) + { + Annotate(typeDefinition.Interfaces[i], annotatedTypeDefinition.Interfaces[j], attributesOfInterest); + } + } + } for (var i = 0; i < typeDefinition.GenericParameters.Count; i++) { From 985b6ce3980958bf0e935263aa7798e50f777888 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 29 Sep 2019 22:25:08 -0700 Subject: [PATCH 05/13] Update to 1.0.0-alpha.53 --- Directory.Build.props | 4 ++-- Directory.Build.targets | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 6d5e254..b8d992d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -37,12 +37,12 @@ enable - 3.0.0-preview9-19423-09 + 3.0.0 false - + diff --git a/Directory.Build.targets b/Directory.Build.targets index 4a17d77..341027f 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,13 +1,3 @@ - - - - - - - - - - From c36f776efa99794c0e960554d36faa7f4ae0bed2 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 29 Sep 2019 22:34:23 -0700 Subject: [PATCH 06/13] Update to .NET Core 3.0.100 --- .../TunnelVisionLabs.ReferenceAssemblyAnnotator.csproj | 1 + global.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/TunnelVisionLabs.ReferenceAssemblyAnnotator.csproj b/TunnelVisionLabs.ReferenceAssemblyAnnotator/TunnelVisionLabs.ReferenceAssemblyAnnotator.csproj index e0c23d3..3547a2f 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/TunnelVisionLabs.ReferenceAssemblyAnnotator.csproj +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/TunnelVisionLabs.ReferenceAssemblyAnnotator.csproj @@ -3,6 +3,7 @@ netstandard2.0;net472 + $(NoWarn),NU5128 true true true diff --git a/global.json b/global.json index 9847f02..79422f0 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "2.1.801" + "version": "3.0.100" } } From e57327e7c74cbf2c4e23de0c6750aab4dc8f3cac Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 30 Sep 2019 07:26:12 -0700 Subject: [PATCH 07/13] Fix NullReferenceException when ReferenceAssemblyAttribute is not found --- .../CustomAttributeFactory.cs | 7 +++++-- .../Program.cs | 3 +++ .../WellKnownTypes.cs | 18 ++++++++++++------ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/CustomAttributeFactory.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/CustomAttributeFactory.cs index c5a1771..a2b440f 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/CustomAttributeFactory.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/CustomAttributeFactory.cs @@ -77,9 +77,12 @@ public CustomAttribute AttributeUsage(AttributeTargets validOn, bool? allowMulti return customAttribute; } - public CustomAttribute ReferenceAssembly() + public CustomAttribute? ReferenceAssembly() { - MethodDefinition constructor = _wellKnownTypes.SystemRuntimeCompilerServicesReferenceAssemblyAttribute.Resolve().Methods.Single(method => method.IsConstructor && !method.IsStatic && method.Parameters.Count == 0); + MethodDefinition? constructor = _wellKnownTypes.SystemRuntimeCompilerServicesReferenceAssemblyAttribute?.Resolve().Methods.Single(method => method.IsConstructor && !method.IsStatic && method.Parameters.Count == 0); + if (constructor is null) + return null; + var customAttribute = new CustomAttribute(_wellKnownTypes.Module.ImportReference(constructor)); return customAttribute; } diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs index 36e1011..59a13d2 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs @@ -541,6 +541,9 @@ private static void EnsureReferenceAssemblyAttribute(AssemblyDefinition assembly } var customAttribute = attributeFactory.ReferenceAssembly(); + if (customAttribute is null) + return; + assemblyDefinition.CustomAttributes.Add(customAttribute); } } diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs index 8833695..deb3ffa 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs @@ -13,10 +13,10 @@ public WellKnownTypes(ModuleDefinition module) { Module = module; - SystemAttribute = ResolveWellKnownType(module, typeof(Attribute)); - SystemAttributeTargets = ResolveWellKnownType(module, typeof(AttributeTargets)); - SystemAttributeUsageAttribute = ResolveWellKnownType(module, typeof(AttributeUsageAttribute)); - SystemRuntimeCompilerServicesCompilerGeneratedAttribute = ResolveWellKnownType(module, typeof(CompilerGeneratedAttribute)); + SystemAttribute = ResolveRequiredWellKnownType(module, typeof(Attribute)); + SystemAttributeTargets = ResolveRequiredWellKnownType(module, typeof(AttributeTargets)); + SystemAttributeUsageAttribute = ResolveRequiredWellKnownType(module, typeof(AttributeUsageAttribute)); + SystemRuntimeCompilerServicesCompilerGeneratedAttribute = ResolveRequiredWellKnownType(module, typeof(CompilerGeneratedAttribute)); SystemRuntimeCompilerServicesReferenceAssemblyAttribute = ResolveWellKnownType(module, typeof(ReferenceAssemblyAttribute)); } @@ -32,9 +32,15 @@ public WellKnownTypes(ModuleDefinition module) public TypeReference SystemRuntimeCompilerServicesCompilerGeneratedAttribute { get; } - public TypeReference SystemRuntimeCompilerServicesReferenceAssemblyAttribute { get; } + public TypeReference? SystemRuntimeCompilerServicesReferenceAssemblyAttribute { get; } - private static TypeDefinition ResolveWellKnownType(ModuleDefinition module, Type type) + private static TypeDefinition ResolveRequiredWellKnownType(ModuleDefinition module, Type type) + { + return ResolveWellKnownType(module, type) + ?? throw new NotSupportedException($"Failed to resolve type '{type.FullName}'"); + } + + private static TypeDefinition? ResolveWellKnownType(ModuleDefinition module, Type type) { return module.TypeSystem.Object.Resolve().Module.GetType(type.FullName); } From 9eef95257258149c6ff0fc05b7e228cb8616c4a4 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 30 Sep 2019 08:30:04 -0700 Subject: [PATCH 08/13] Define ReferenceAssemblyAttribute when not in the standard library --- .../CustomAttributeFactory.cs | 7 +-- .../MethodFactory.cs | 8 +-- .../Program.cs | 53 ++++++++++++------- .../TypeDefinitionExtensions.cs | 5 +- .../WellKnownTypes.cs | 20 ++++--- 5 files changed, 55 insertions(+), 38 deletions(-) diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/CustomAttributeFactory.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/CustomAttributeFactory.cs index a2b440f..c5a1771 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/CustomAttributeFactory.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/CustomAttributeFactory.cs @@ -77,12 +77,9 @@ public CustomAttribute AttributeUsage(AttributeTargets validOn, bool? allowMulti return customAttribute; } - public CustomAttribute? ReferenceAssembly() + public CustomAttribute ReferenceAssembly() { - MethodDefinition? constructor = _wellKnownTypes.SystemRuntimeCompilerServicesReferenceAssemblyAttribute?.Resolve().Methods.Single(method => method.IsConstructor && !method.IsStatic && method.Parameters.Count == 0); - if (constructor is null) - return null; - + MethodDefinition constructor = _wellKnownTypes.SystemRuntimeCompilerServicesReferenceAssemblyAttribute.Resolve().Methods.Single(method => method.IsConstructor && !method.IsStatic && method.Parameters.Count == 0); var customAttribute = new CustomAttribute(_wellKnownTypes.Module.ImportReference(constructor)); return customAttribute; } diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/MethodFactory.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/MethodFactory.cs index 8b7aa09..abcd6a0 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/MethodFactory.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/MethodFactory.cs @@ -8,12 +8,12 @@ namespace TunnelVisionLabs.ReferenceAssemblyAnnotator internal static class MethodFactory { - public static MethodDefinition DefaultConstructor(WellKnownTypes wellKnownTypes) - => Constructor(wellKnownTypes); + public static MethodDefinition DefaultConstructor(TypeSystem typeSystem) + => Constructor(typeSystem); - public static MethodDefinition Constructor(WellKnownTypes wellKnownTypes) + public static MethodDefinition Constructor(TypeSystem typeSystem) { - var constructor = new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, wellKnownTypes.TypeSystem.Void); + var constructor = new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, typeSystem.Void); constructor.Body = new MethodBody(constructor) { Instructions = diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs index 59a13d2..59477f3 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs @@ -33,7 +33,7 @@ internal static void Main(TaskLoggingHelper? log, string referenceAssembly, stri annotatedAssemblyResolver.AddSearchDirectory(Path.GetDirectoryName(annotatedReferenceAssembly)); using var annotatedAssemblyDefinition = AssemblyDefinition.ReadAssembly(annotatedReferenceAssembly, new ReaderParameters(ReadingMode.Immediate) { AssemblyResolver = annotatedAssemblyResolver }); - var wellKnownTypes = new WellKnownTypes(assemblyDefinition.MainModule); + var wellKnownTypes = new WellKnownTypes(assemblyDefinition, DefineReferenceAssemblyAttribute); // Define embedded types used by the compiler var embeddedAttribute = DefineEmbeddedAttribute(assemblyDefinition, wellKnownTypes); @@ -292,7 +292,7 @@ private static TypeDefinition DefineEmbeddedAttribute(AssemblyDefinition assembl TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, wellKnownTypes.Module.ImportReference(wellKnownTypes.SystemAttribute)); - var constructor = attribute.AddDefaultConstructor(wellKnownTypes); + var constructor = attribute.AddDefaultConstructor(wellKnownTypes.TypeSystem); MethodDefinition compilerGeneratedConstructor = wellKnownTypes.SystemRuntimeCompilerServicesCompilerGeneratedAttribute.Resolve().Methods.Single(method => method.IsConstructor && !method.IsStatic && method.Parameters.Count == 0); var customAttribute = new CustomAttribute(wellKnownTypes.Module.ImportReference(compilerGeneratedConstructor)); @@ -304,6 +304,26 @@ private static TypeDefinition DefineEmbeddedAttribute(AssemblyDefinition assembl return attribute; } + private static TypeDefinition DefineReferenceAssemblyAttribute(AssemblyDefinition assemblyDefinition, (TypeReference systemAttribute, TypeReference systemRuntimeCompilerServicesCompilerGeneratedAttribute) wellKnownTypes) + { + var attribute = new TypeDefinition( + @namespace: "System.Runtime.CompilerServices", + name: "ReferenceAssemblyAttribute", + TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, + assemblyDefinition.MainModule.ImportReference(wellKnownTypes.systemAttribute)); + + var constructor = attribute.AddDefaultConstructor(assemblyDefinition.MainModule.TypeSystem); + + MethodDefinition compilerGeneratedConstructor = wellKnownTypes.systemRuntimeCompilerServicesCompilerGeneratedAttribute.Resolve().Methods.Single(method => method.IsConstructor && !method.IsStatic && method.Parameters.Count == 0); + var customAttribute = new CustomAttribute(assemblyDefinition.MainModule.ImportReference(compilerGeneratedConstructor)); + attribute.CustomAttributes.Add(customAttribute); + attribute.CustomAttributes.Add(new CustomAttribute(constructor)); + + assemblyDefinition.MainModule.Types.Add(attribute); + + return attribute; + } + private static TypeDefinition DefineNullableAttribute(AssemblyDefinition assemblyDefinition, TypeReference embeddedAttribute, WellKnownTypes wellKnownTypes) { var attribute = new TypeDefinition( @@ -316,10 +336,10 @@ private static TypeDefinition DefineNullableAttribute(AssemblyDefinition assembl attribute.CustomAttributes.Add(new CustomAttribute(wellKnownTypes.Module.ImportReference(compilerGeneratedConstructor))); attribute.CustomAttributes.Add(new CustomAttribute(embeddedAttribute.Resolve().Methods.Single(method => method.IsConstructor && !method.IsStatic && method.Parameters.Count == 0))); - var constructorByte = MethodFactory.Constructor(wellKnownTypes); + var constructorByte = MethodFactory.Constructor(wellKnownTypes.TypeSystem); constructorByte.Parameters.Add(new ParameterDefinition(wellKnownTypes.TypeSystem.Byte)); - var constructorByteArray = MethodFactory.Constructor(wellKnownTypes); + var constructorByteArray = MethodFactory.Constructor(wellKnownTypes.TypeSystem); constructorByteArray.Parameters.Add(new ParameterDefinition(new ArrayType(wellKnownTypes.TypeSystem.Byte))); attribute.Methods.Add(constructorByte); @@ -342,7 +362,7 @@ private static TypeDefinition DefineNullableContextAttribute(AssemblyDefinition attribute.CustomAttributes.Add(new CustomAttribute(wellKnownTypes.Module.ImportReference(compilerGeneratedConstructor))); attribute.CustomAttributes.Add(new CustomAttribute(embeddedAttribute.Resolve().Methods.Single(method => method.IsConstructor && !method.IsStatic && method.Parameters.Count == 0))); - var constructor = MethodFactory.Constructor(wellKnownTypes); + var constructor = MethodFactory.Constructor(wellKnownTypes.TypeSystem); constructor.Parameters.Add(new ParameterDefinition(wellKnownTypes.TypeSystem.Byte)); attribute.Methods.Add(constructor); @@ -363,7 +383,7 @@ private static TypeDefinition DefineNullablePublicOnlyAttribute(AssemblyDefiniti attribute.CustomAttributes.Add(new CustomAttribute(wellKnownTypes.Module.ImportReference(compilerGeneratedConstructor))); attribute.CustomAttributes.Add(new CustomAttribute(embeddedAttribute.Resolve().Methods.Single(method => method.IsConstructor && !method.IsStatic && method.Parameters.Count == 0))); - var constructor = MethodFactory.Constructor(wellKnownTypes); + var constructor = MethodFactory.Constructor(wellKnownTypes.TypeSystem); constructor.Parameters.Add(new ParameterDefinition(wellKnownTypes.TypeSystem.Boolean)); attribute.Methods.Add(constructor); @@ -380,7 +400,7 @@ private static TypeDefinition DefineAllowNullAttribute(AssemblyDefinition assemb TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, wellKnownTypes.Module.ImportReference(wellKnownTypes.SystemAttribute)); - attribute.AddDefaultConstructor(wellKnownTypes); + attribute.AddDefaultConstructor(wellKnownTypes.TypeSystem); attribute.CustomAttributes.Add(attributeFactory.AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, inherited: false)); assemblyDefinition.MainModule.Types.Add(attribute); @@ -396,7 +416,7 @@ private static TypeDefinition DefineDisallowNullAttribute(AssemblyDefinition ass TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, wellKnownTypes.Module.ImportReference(wellKnownTypes.SystemAttribute)); - attribute.AddDefaultConstructor(wellKnownTypes); + attribute.AddDefaultConstructor(wellKnownTypes.TypeSystem); attribute.CustomAttributes.Add(attributeFactory.AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, inherited: false)); assemblyDefinition.MainModule.Types.Add(attribute); @@ -412,7 +432,7 @@ private static TypeDefinition DefineDoesNotReturnAttribute(AssemblyDefinition as TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, wellKnownTypes.Module.ImportReference(wellKnownTypes.SystemAttribute)); - attribute.AddDefaultConstructor(wellKnownTypes); + attribute.AddDefaultConstructor(wellKnownTypes.TypeSystem); attribute.CustomAttributes.Add(attributeFactory.AttributeUsage(AttributeTargets.Method, inherited: false)); assemblyDefinition.MainModule.Types.Add(attribute); @@ -428,7 +448,7 @@ private static TypeDefinition DefineDoesNotReturnIfAttribute(AssemblyDefinition TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, wellKnownTypes.Module.ImportReference(wellKnownTypes.SystemAttribute)); - var constructor = MethodFactory.Constructor(wellKnownTypes); + var constructor = MethodFactory.Constructor(wellKnownTypes.TypeSystem); constructor.Parameters.Add(new ParameterDefinition("parameterValue", ParameterAttributes.None, wellKnownTypes.TypeSystem.Boolean)); attribute.Methods.Add(constructor); @@ -447,7 +467,7 @@ private static TypeDefinition DefineMaybeNullAttribute(AssemblyDefinition assemb TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, wellKnownTypes.Module.ImportReference(wellKnownTypes.SystemAttribute)); - attribute.AddDefaultConstructor(wellKnownTypes); + attribute.AddDefaultConstructor(wellKnownTypes.TypeSystem); attribute.CustomAttributes.Add(attributeFactory.AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, inherited: false)); assemblyDefinition.MainModule.Types.Add(attribute); @@ -463,7 +483,7 @@ private static TypeDefinition DefineMaybeNullWhenAttribute(AssemblyDefinition as TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, wellKnownTypes.Module.ImportReference(wellKnownTypes.SystemAttribute)); - var constructor = MethodFactory.Constructor(wellKnownTypes); + var constructor = MethodFactory.Constructor(wellKnownTypes.TypeSystem); constructor.Parameters.Add(new ParameterDefinition("returnValue", ParameterAttributes.None, wellKnownTypes.TypeSystem.Boolean)); attribute.Methods.Add(constructor); @@ -482,7 +502,7 @@ private static TypeDefinition DefineNotNullAttribute(AssemblyDefinition assembly TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, wellKnownTypes.Module.ImportReference(wellKnownTypes.SystemAttribute)); - attribute.AddDefaultConstructor(wellKnownTypes); + attribute.AddDefaultConstructor(wellKnownTypes.TypeSystem); attribute.CustomAttributes.Add(attributeFactory.AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, inherited: false)); assemblyDefinition.MainModule.Types.Add(attribute); @@ -502,7 +522,7 @@ private static TypeDefinition DefineNotNullIfNotNullAttribute(AssemblyDefinition attribute.CustomAttributes.Add(attributeFactory.Nullable(0)); attribute.CustomAttributes.Add(attributeFactory.AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, allowMultiple: true, inherited: false)); - var constructor = MethodFactory.Constructor(wellKnownTypes); + var constructor = MethodFactory.Constructor(wellKnownTypes.TypeSystem); constructor.Parameters.Add(new ParameterDefinition("parameterName", ParameterAttributes.None, wellKnownTypes.TypeSystem.String)); attribute.Methods.Add(constructor); @@ -519,7 +539,7 @@ private static TypeDefinition DefineNotNullWhenAttribute(AssemblyDefinition asse TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, wellKnownTypes.Module.ImportReference(wellKnownTypes.SystemAttribute)); - var constructor = MethodFactory.Constructor(wellKnownTypes); + var constructor = MethodFactory.Constructor(wellKnownTypes.TypeSystem); constructor.Parameters.Add(new ParameterDefinition("returnValue", ParameterAttributes.None, wellKnownTypes.TypeSystem.Boolean)); attribute.Methods.Add(constructor); @@ -541,9 +561,6 @@ private static void EnsureReferenceAssemblyAttribute(AssemblyDefinition assembly } var customAttribute = attributeFactory.ReferenceAssembly(); - if (customAttribute is null) - return; - assemblyDefinition.CustomAttributes.Add(customAttribute); } } diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/TypeDefinitionExtensions.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/TypeDefinitionExtensions.cs index 84bcb8a..47b5101 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/TypeDefinitionExtensions.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/TypeDefinitionExtensions.cs @@ -4,13 +4,12 @@ namespace TunnelVisionLabs.ReferenceAssemblyAnnotator { using Mono.Cecil; - using Mono.Cecil.Cil; internal static class TypeDefinitionExtensions { - public static MethodDefinition AddDefaultConstructor(this TypeDefinition typeDefinition, WellKnownTypes wellKnownTypes) + public static MethodDefinition AddDefaultConstructor(this TypeDefinition typeDefinition, TypeSystem typeSystem) { - MethodDefinition constructor = MethodFactory.DefaultConstructor(wellKnownTypes); + MethodDefinition constructor = MethodFactory.DefaultConstructor(typeSystem); typeDefinition.Methods.Add(constructor); return constructor; } diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs index deb3ffa..66537e3 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs @@ -9,15 +9,19 @@ namespace TunnelVisionLabs.ReferenceAssemblyAnnotator internal class WellKnownTypes { - public WellKnownTypes(ModuleDefinition module) + public WellKnownTypes(AssemblyDefinition assemblyDefinition, Func defineReferenceAssemblyAttribute) { - Module = module; + Module = assemblyDefinition.MainModule; - SystemAttribute = ResolveRequiredWellKnownType(module, typeof(Attribute)); - SystemAttributeTargets = ResolveRequiredWellKnownType(module, typeof(AttributeTargets)); - SystemAttributeUsageAttribute = ResolveRequiredWellKnownType(module, typeof(AttributeUsageAttribute)); - SystemRuntimeCompilerServicesCompilerGeneratedAttribute = ResolveRequiredWellKnownType(module, typeof(CompilerGeneratedAttribute)); - SystemRuntimeCompilerServicesReferenceAssemblyAttribute = ResolveWellKnownType(module, typeof(ReferenceAssemblyAttribute)); + SystemAttribute = ResolveRequiredWellKnownType(Module, typeof(Attribute)); + SystemAttributeTargets = ResolveRequiredWellKnownType(Module, typeof(AttributeTargets)); + SystemAttributeUsageAttribute = ResolveRequiredWellKnownType(Module, typeof(AttributeUsageAttribute)); + SystemRuntimeCompilerServicesCompilerGeneratedAttribute = ResolveRequiredWellKnownType(Module, typeof(CompilerGeneratedAttribute)); + + SystemRuntimeCompilerServicesReferenceAssemblyAttribute = ResolveWellKnownType(Module, typeof(ReferenceAssemblyAttribute)) + ?? defineReferenceAssemblyAttribute( + assemblyDefinition, + (systemAttribute: SystemAttribute, systemRuntimeCompilerServicesCompilerGeneratedAttribute: SystemRuntimeCompilerServicesCompilerGeneratedAttribute)); } public ModuleDefinition Module { get; } @@ -32,7 +36,7 @@ public WellKnownTypes(ModuleDefinition module) public TypeReference SystemRuntimeCompilerServicesCompilerGeneratedAttribute { get; } - public TypeReference? SystemRuntimeCompilerServicesReferenceAssemblyAttribute { get; } + public TypeReference SystemRuntimeCompilerServicesReferenceAssemblyAttribute { get; } private static TypeDefinition ResolveRequiredWellKnownType(ModuleDefinition module, Type type) { From b87e5b73dfd9fab0930bf84a2c1f5b45cdb331ca Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 30 Sep 2019 08:32:27 -0700 Subject: [PATCH 09/13] Set rollForward=latestFeature --- global.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/global.json b/global.json index 79422f0..40f698c 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,6 @@ { "sdk": { - "version": "3.0.100" + "version": "3.0.100", + "rollForward": "latestFeature" } } From 3a4d94e629e5ccff3726ea60b8625c0ee0cf5b46 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 30 Sep 2019 08:40:08 -0700 Subject: [PATCH 10/13] Use built in types consistently --- .editorconfig | 2 +- .../AnnotatorBuildTask.cs | 6 +++--- TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.editorconfig b/.editorconfig index bedaa4a..dd3f821 100644 --- a/.editorconfig +++ b/.editorconfig @@ -65,7 +65,7 @@ dotnet_code_quality_unused_parameters = all:suggestion # var preferences csharp_style_var_elsewhere = false:silent -csharp_style_var_for_built_in_types = false:none +csharp_style_var_for_built_in_types = false:warning csharp_style_var_when_type_is_apparent = true:silent # Expression-bodied members diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/AnnotatorBuildTask.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/AnnotatorBuildTask.cs index 36d3f68..5a05e6f 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/AnnotatorBuildTask.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/AnnotatorBuildTask.cs @@ -57,8 +57,8 @@ public ITaskItem[]? GeneratedAssemblies public override bool Execute() { - var unannotatedReferenceAssembly = TargetFrameworkDirectories.Select(path => Path.Combine(path.ItemSpec, UnannotatedReferenceAssembly + ".dll")).FirstOrDefault(File.Exists); - var annotatedReferenceAssembly = Path.Combine(AnnotatedReferenceAssemblyDirectory, UnannotatedReferenceAssembly + ".dll"); + string unannotatedReferenceAssembly = TargetFrameworkDirectories.Select(path => Path.Combine(path.ItemSpec, UnannotatedReferenceAssembly + ".dll")).FirstOrDefault(File.Exists); + string annotatedReferenceAssembly = Path.Combine(AnnotatedReferenceAssemblyDirectory, UnannotatedReferenceAssembly + ".dll"); bool foundAnnotatedAssembly = File.Exists(annotatedReferenceAssembly); Log.LogMessage($"Generating reference assembly for {UnannotatedReferenceAssembly}"); @@ -79,7 +79,7 @@ public override bool Execute() } Directory.CreateDirectory(OutputPath); - var outputAssembly = Path.Combine(OutputPath, Path.GetFileName(unannotatedReferenceAssembly)); + string outputAssembly = Path.Combine(OutputPath, Path.GetFileName(unannotatedReferenceAssembly)); Program.Main(Log, unannotatedReferenceAssembly, annotatedReferenceAssembly, outputAssembly); GeneratedAssemblies = new[] { new TaskItem(outputAssembly) }; diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs index 59477f3..61bdc23 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs @@ -106,7 +106,7 @@ private static void AnnotateType(TaskLoggingHelper? log, TypeDefinition typeDefi } Annotate(typeDefinition, annotatedTypeDefinition, attributesOfInterest); - for (var i = 0; i < typeDefinition.Interfaces.Count; i++) + for (int i = 0; i < typeDefinition.Interfaces.Count; i++) { for (int j = 0; j < annotatedTypeDefinition.Interfaces.Count; j++) { @@ -117,7 +117,7 @@ private static void AnnotateType(TaskLoggingHelper? log, TypeDefinition typeDefi } } - for (var i = 0; i < typeDefinition.GenericParameters.Count; i++) + for (int i = 0; i < typeDefinition.GenericParameters.Count; i++) { Annotate(typeDefinition.GenericParameters[i], annotatedTypeDefinition.GenericParameters[i], attributesOfInterest); } @@ -194,7 +194,7 @@ private static void Annotate(ICustomAttributeProvider provider, ICustomAttribute continue; var newCustomAttribute = new CustomAttribute(constructor); - for (var i = 0; i < customAttribute.ConstructorArguments.Count; i++) + for (int i = 0; i < customAttribute.ConstructorArguments.Count; i++) { newCustomAttribute.ConstructorArguments.Add(new CustomAttributeArgument(constructor.Parameters[i].ParameterType, customAttribute.ConstructorArguments[i].Value)); } From 95580d7f6717cdf6d06ccc61d1bcd88575b2e627 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 30 Sep 2019 08:40:48 -0700 Subject: [PATCH 11/13] Remove unused parameter --- TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs index 61bdc23..80e6983 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs @@ -55,7 +55,7 @@ internal static void Main(TaskLoggingHelper? log, string referenceAssembly, stri var notNullWhenAttribute = DefineNotNullWhenAttribute(assemblyDefinition, wellKnownTypes, attributeFactory); // Ensure the assembly is marked with ReferenceAssemblyAttribute - EnsureReferenceAssemblyAttribute(assemblyDefinition, wellKnownTypes, attributeFactory); + EnsureReferenceAssemblyAttribute(assemblyDefinition, attributeFactory); var attributesOfInterest = new Dictionary(); attributesOfInterest.Add(nullableAttribute.FullName, nullableAttribute); @@ -550,7 +550,7 @@ private static TypeDefinition DefineNotNullWhenAttribute(AssemblyDefinition asse return attribute; } - private static void EnsureReferenceAssemblyAttribute(AssemblyDefinition assemblyDefinition, WellKnownTypes wellKnownTypes, CustomAttributeFactory attributeFactory) + private static void EnsureReferenceAssemblyAttribute(AssemblyDefinition assemblyDefinition, CustomAttributeFactory attributeFactory) { foreach (var attribute in assemblyDefinition.CustomAttributes) { From f2b25a4f5501bdc17e35795150ab5a2997c516f3 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 30 Sep 2019 08:50:35 -0700 Subject: [PATCH 12/13] Avoid using ReferenceAssemblyAttribute on itself The DefineReferenceAssemblyAttribute method was originally copied from DefineEmbeddedAttribute. The latter intentionally applies the attribute to itself. ReferenceAssemblyAttribute would better be defined by applying EmbeddedAttribute to it, but the initialization order doesn't allow that to easily occur at this time. --- TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs index 80e6983..fa7dbe9 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs @@ -317,7 +317,6 @@ private static TypeDefinition DefineReferenceAssemblyAttribute(AssemblyDefinitio MethodDefinition compilerGeneratedConstructor = wellKnownTypes.systemRuntimeCompilerServicesCompilerGeneratedAttribute.Resolve().Methods.Single(method => method.IsConstructor && !method.IsStatic && method.Parameters.Count == 0); var customAttribute = new CustomAttribute(assemblyDefinition.MainModule.ImportReference(compilerGeneratedConstructor)); attribute.CustomAttributes.Add(customAttribute); - attribute.CustomAttributes.Add(new CustomAttribute(constructor)); assemblyDefinition.MainModule.Types.Add(attribute); From ff64d81482a7db5cee28eb6beb3a58736210082c Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 30 Sep 2019 09:51:40 -0700 Subject: [PATCH 13/13] Remove unused local --- TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs index fa7dbe9..ceaf229 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/Program.cs @@ -312,7 +312,7 @@ private static TypeDefinition DefineReferenceAssemblyAttribute(AssemblyDefinitio TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, assemblyDefinition.MainModule.ImportReference(wellKnownTypes.systemAttribute)); - var constructor = attribute.AddDefaultConstructor(assemblyDefinition.MainModule.TypeSystem); + attribute.AddDefaultConstructor(assemblyDefinition.MainModule.TypeSystem); MethodDefinition compilerGeneratedConstructor = wellKnownTypes.systemRuntimeCompilerServicesCompilerGeneratedAttribute.Resolve().Methods.Single(method => method.IsConstructor && !method.IsStatic && method.Parameters.Count == 0); var customAttribute = new CustomAttribute(assemblyDefinition.MainModule.ImportReference(compilerGeneratedConstructor));