diff --git a/docs/error-codes.md b/docs/error-codes.md index 85dc1efc8c84..2f3fa3f53416 100644 --- a/docs/error-codes.md +++ b/docs/error-codes.md @@ -69,6 +69,10 @@ the error code. For example: - The value given for the --warn argument was not a valid warning version. Valid versions include integers in the range 0-9999, though not all of these map to distinct warning waves. +#### `IL1017`: Invalid value 'value' for '--generate-warning-suppressions' option + +- Invalid value 'value' was used for command-line option '--generate-warning-suppressions'; must be 'cs' or 'xml'. + ---- ## Warning Codes diff --git a/docs/illink-options.md b/docs/illink-options.md index 7d8c52bd15fd..648a2d5967d5 100644 --- a/docs/illink-options.md +++ b/docs/illink-options.md @@ -170,12 +170,14 @@ warnings. ### Generating warning suppressions -For each of the linked assemblies that triggered any warnings during the linking, the -`--generate-warning-suppressions` option will generate a file containing a list with the -necessary attributes to suppres these. The attributes contained in this files are -assembly-level attributes of type `UnconditionalSuppressMessage` specifying the required -`Scope` and `Target` properties for each of the warnings seen. The generated files are -saved in the ouput directory and named `.WarningSuppressions.cs`. +For each of the linked assemblies that triggered any warnings during linking, the +`--generate-warning-suppressions [cs | xml]` option will generate a file containing a list +with the necessary attributes to suppress these. The generated files can either be C# source +files or XML files in a [format](data-formats.md#custom-attributes-annotations-format) that is supported by the linker, +the emitted format depends upon the argument that is passed to this option (`cs` or `xml`.) +The attributes contained in these files are assembly-level attributes of type `UnconditionalSuppressMessage` +specifying the required `Scope` and `Target` properties for each of the warnings seen. The +generated files are saved in the output directory and named `.WarningSuppressions.`. ## monolinker specific options diff --git a/src/linker/Linker/DocumentationSignatureGenerator.cs b/src/linker/Linker/DocumentationSignatureGenerator.cs index 6bbff73bb023..227b3223cd3b 100644 --- a/src/linker/Linker/DocumentationSignatureGenerator.cs +++ b/src/linker/Linker/DocumentationSignatureGenerator.cs @@ -16,6 +16,12 @@ namespace Mono.Linker /// public sealed partial class DocumentationSignatureGenerator { + internal const string MethodPrefix = "M:"; + internal const string FieldPrefix = "F:"; + internal const string EventPrefix = "E:"; + internal const string PropertyPrefix = "P:"; + internal const string TypePrefix = "T:"; + public static readonly DocumentationSignatureGenerator Instance = new DocumentationSignatureGenerator (); private DocumentationSignatureGenerator () @@ -47,31 +53,31 @@ public void VisitMember (IMemberDefinition member, StringBuilder builder) private void VisitMethod (MethodDefinition method, StringBuilder builder) { - builder.Append ("M:"); + builder.Append (MethodPrefix); PartVisitor.Instance.VisitMethodDefinition (method, builder); } private void VisitField (FieldDefinition field, StringBuilder builder) { - builder.Append ("F:"); + builder.Append (FieldPrefix); PartVisitor.Instance.VisitField (field, builder); } private void VisitEvent (EventDefinition evt, StringBuilder builder) { - builder.Append ("E:"); + builder.Append (EventPrefix); PartVisitor.Instance.VisitEvent (evt, builder); } private void VisitProperty (PropertyDefinition property, StringBuilder builder) { - builder.Append ("P:"); + builder.Append (PropertyPrefix); PartVisitor.Instance.VisitProperty (property, builder); } private void VisitTypeDefinition (TypeDefinition type, StringBuilder builder) { - builder.Append ("T:"); + builder.Append (TypePrefix); PartVisitor.Instance.VisitTypeReference (type, builder); } } diff --git a/src/linker/Linker/Driver.cs b/src/linker/Linker/Driver.cs index e75553021d63..60f13caedcd5 100644 --- a/src/linker/Linker/Driver.cs +++ b/src/linker/Linker/Driver.cs @@ -426,7 +426,17 @@ protected int SetupContext (ILogger customLogger = null) continue; case "--generate-warning-suppressions": + string generateWarningSuppressionsArgument = string.Empty; + if (!GetStringParam (token, l => generateWarningSuppressionsArgument = l)) + return -1; + + if (!GetWarningSuppressionWriterFileOutputKind (generateWarningSuppressionsArgument, out var fileOutputKind)) { + context.LogError ($"Invalid value '{generateWarningSuppressionsArgument}' for '--generate-warning-suppressions' option", 1017); + return -1; + } + context.OutputWarningSuppressions = true; + context.SetWarningSuppressionWriter (fileOutputKind); continue; case "--nowarn": @@ -990,6 +1000,23 @@ static bool GetOptimizationName (string text, out CodeOptimizations optimization return false; } + static bool GetWarningSuppressionWriterFileOutputKind (string text, out WarningSuppressionWriter.FileOutputKind fileOutputKind) + { + switch (text.ToLowerInvariant ()) { + case "cs": + fileOutputKind = WarningSuppressionWriter.FileOutputKind.CSharp; + return true; + + case "xml": + fileOutputKind = WarningSuppressionWriter.FileOutputKind.Xml; + return true; + + default: + fileOutputKind = WarningSuppressionWriter.FileOutputKind.CSharp; + return false; + } + } + bool GetBoolParam (string token, Action action) { if (arguments.Count == 0) { diff --git a/src/linker/Linker/LinkContext.cs b/src/linker/Linker/LinkContext.cs index 60629e53b5b1..331f51ba9894 100644 --- a/src/linker/Linker/LinkContext.cs +++ b/src/linker/Linker/LinkContext.cs @@ -172,7 +172,7 @@ public ISymbolWriterProvider SymbolWriterProvider { public KnownMembers MarkedKnownMembers { get; private set; } - public WarningSuppressionWriter WarningSuppressionWriter { get; } + public WarningSuppressionWriter WarningSuppressionWriter { get; private set; } public HashSet NoWarn { get; set; } @@ -236,7 +236,6 @@ public LinkContext (Pipeline pipeline, AssemblyResolver resolver, ReaderParamete StripLinkAttributes = true; PInvokes = new List (); Suppressions = new UnconditionalSuppressMessageAttributeState (this); - WarningSuppressionWriter = new WarningSuppressionWriter (this); NoWarn = new HashSet (); GeneralWarnAsError = false; WarnAsError = new Dictionary (); @@ -624,6 +623,11 @@ public static WarnVersion GetWarningVersion (int code) // This should return an increasing WarnVersion for new warning waves. return WarnVersion.ILLink5; } + + public void SetWarningSuppressionWriter (WarningSuppressionWriter.FileOutputKind fileOutputKind) + { + WarningSuppressionWriter = new WarningSuppressionWriter (this, fileOutputKind); + } } public class CodeOptimizationsSettings diff --git a/src/linker/Linker/UnconditionalSuppressMessageAttributeState.cs b/src/linker/Linker/UnconditionalSuppressMessageAttributeState.cs index adbff8eabae2..385fa30eac79 100644 --- a/src/linker/Linker/UnconditionalSuppressMessageAttributeState.cs +++ b/src/linker/Linker/UnconditionalSuppressMessageAttributeState.cs @@ -6,6 +6,10 @@ namespace Mono.Linker { public class UnconditionalSuppressMessageAttributeState { + internal const string ScopeProperty = "Scope"; + internal const string TargetProperty = "Target"; + internal const string MessageIdProperty = "MessageId"; + private readonly LinkContext _context; private readonly Dictionary> _suppressions; private HashSet InitializedAssemblies { get; } @@ -99,13 +103,13 @@ private static bool TryDecodeSuppressMessageAttributeData (CustomAttribute attri if (attribute.HasProperties) { foreach (var p in attribute.Properties) { switch (p.Name) { - case "Scope": + case ScopeProperty: info.Scope = (p.Argument.Value as string)?.ToLower (); break; - case "Target": + case TargetProperty: info.Target = p.Argument.Value as string; break; - case "MessageId": + case MessageIdProperty: info.MessageId = p.Argument.Value as string; break; } diff --git a/src/linker/Linker/WarningSuppressionWriter.cs b/src/linker/Linker/WarningSuppressionWriter.cs index bfa1bbc84564..5b62ea101380 100644 --- a/src/linker/Linker/WarningSuppressionWriter.cs +++ b/src/linker/Linker/WarningSuppressionWriter.cs @@ -2,6 +2,8 @@ using System.IO; using System.Linq; using System.Text; +using System.Xml; +using System.Xml.Linq; using Mono.Cecil; namespace Mono.Linker @@ -9,12 +11,15 @@ namespace Mono.Linker public class WarningSuppressionWriter { private readonly LinkContext _context; - private readonly Dictionary> _warnings; + private readonly Dictionary> _warnings; + private readonly FileOutputKind _fileOutputKind; - public WarningSuppressionWriter (LinkContext context) + public WarningSuppressionWriter (LinkContext context, + FileOutputKind fileOutputKind = FileOutputKind.CSharp) { _context = context; _warnings = new Dictionary> (); + _fileOutputKind = fileOutputKind; } public void AddWarning (int code, IMemberDefinition memberDefinition) @@ -31,46 +36,82 @@ public void AddWarning (int code, IMemberDefinition memberDefinition) public void OutputSuppressions () { foreach (var assemblyName in _warnings.Keys) { - using (var sw = new StreamWriter (Path.Combine (_context.OutputDirectory, $"{assemblyName.Name}.WarningSuppressions.cs"))) { - StringBuilder sb = new StringBuilder ("using System.Diagnostics.CodeAnalysis;").AppendLine ().AppendLine (); - List<(int Code, IMemberDefinition Member)> listOfWarnings = _warnings[assemblyName].ToList (); - listOfWarnings.Sort ((a, b) => { - string lhs = a.Member is MethodReference lhsMethod ? lhsMethod.GetDisplayName () : a.Member.FullName; - string rhs = b.Member is MethodReference rhsMethod ? rhsMethod.GetDisplayName () : b.Member.FullName; - if (lhs == rhs) - return a.Code.CompareTo (b.Code); + if (_fileOutputKind == FileOutputKind.Xml) { + OutputSuppressionsXmlFormat (assemblyName); + } else { + OutputSuppressionsCSharpFormat (assemblyName); + } + } + } - return string.CompareOrdinal (lhs, rhs); - }); + void OutputSuppressionsXmlFormat (AssemblyNameDefinition assemblyName) + { + var xmlTree = + new XElement ("linker", + new XElement ("assembly", new XAttribute ("fullname", assemblyName.FullName))); - foreach (var warning in listOfWarnings) { - int warningCode = warning.Code; - IMemberDefinition warningOrigin = warning.Member; - sb.Append ("[assembly: UnconditionalSuppressMessage (\""); - sb.Append (Constants.ILLink); - sb.Append ("\", \"IL"); - sb.Append (warningCode).Append ("\", Scope = \""); - switch (warningOrigin.MetadataToken.TokenType) { - case TokenType.TypeDef: - sb.Append ("type\", Target = \""); - break; - case TokenType.Method: - case TokenType.Property: - case TokenType.Field: - case TokenType.Event: - sb.Append ("member\", Target = \""); - break; - default: - break; - } + foreach (var warning in GetListOfWarnings (assemblyName)) { + xmlTree.Element ("assembly").Add ( + new XElement ("attribute", + new XAttribute ("fullname", "System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute"), + new XElement ("argument", Constants.ILLink), + new XElement ("argument", $"IL{warning.Code}"), + new XElement ("property", new XAttribute ("name", UnconditionalSuppressMessageAttributeState.ScopeProperty), + GetWarningSuppressionScopeString (warning.MemberDocumentationSignature)), + new XElement ("property", new XAttribute ("name", UnconditionalSuppressMessageAttributeState.TargetProperty), + warning.MemberDocumentationSignature))); + } - DocumentationSignatureGenerator.Instance.VisitMember (warningOrigin, sb); - sb.AppendLine ("\")]"); - } + XDocument xdoc = new XDocument (xmlTree); + using (var xw = XmlWriter.Create (Path.Combine (_context.OutputDirectory, $"{assemblyName.Name}.WarningSuppressions.xml"), + new XmlWriterSettings { Indent = true })) { + xdoc.Save (xw); + } + } - sw.Write (sb.ToString ()); + void OutputSuppressionsCSharpFormat (AssemblyNameDefinition assemblyName) + { + using (var sw = new StreamWriter (Path.Combine (_context.OutputDirectory, $"{assemblyName.Name}.WarningSuppressions.cs"))) { + StringBuilder sb = new StringBuilder ("using System.Diagnostics.CodeAnalysis;").AppendLine ().AppendLine (); + foreach (var warning in GetListOfWarnings (assemblyName)) { + sb.Append ("[assembly: UnconditionalSuppressMessage (\"") + .Append (Constants.ILLink) + .Append ("\", \"IL").Append (warning.Code) + .Append ("\", Scope = \"").Append (GetWarningSuppressionScopeString (warning.MemberDocumentationSignature)) + .Append ("\", Target = \"").Append (warning.MemberDocumentationSignature) + .AppendLine ("\")]"); } + + sw.Write (sb.ToString ()); + } + } + + List<(int Code, string MemberDocumentationSignature)> GetListOfWarnings (AssemblyNameDefinition assemblyName) + { + List<(int Code, string MemberDocumentationSignature)> listOfWarnings = new List<(int Code, string MemberDocumentationSignature)> (); + StringBuilder sb = new StringBuilder (); + foreach (var warning in _warnings[assemblyName].ToList ()) { + DocumentationSignatureGenerator.Instance.VisitMember (warning.Member, sb); + listOfWarnings.Add ((warning.Code, sb.ToString ())); + sb.Clear (); } + + listOfWarnings.Sort (); + return listOfWarnings; + } + + static string GetWarningSuppressionScopeString (string memberDocumentationSignature) + { + if (memberDocumentationSignature.StartsWith (DocumentationSignatureGenerator.TypePrefix)) + return "type"; + + return "member"; } + + public enum FileOutputKind + { + CSharp, + Xml + }; } } diff --git a/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/CanGenerateWarningSuppressionFile.cs b/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/CanGenerateWarningSuppressionFileCSharp.cs similarity index 90% rename from test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/CanGenerateWarningSuppressionFile.cs rename to test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/CanGenerateWarningSuppressionFileCSharp.cs index c81cd8f18d20..a064b83f7d14 100644 --- a/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/CanGenerateWarningSuppressionFile.cs +++ b/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/CanGenerateWarningSuppressionFileCSharp.cs @@ -13,8 +13,8 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression [KeptAssembly ("library.dll")] [SetupLinkerAction ("link", "library.dll")] [SetupLinkerArgument ("--verbose")] - [SetupLinkerArgument ("--generate-warning-suppressions")] - public class CanGenerateWarningSuppressionFile + [SetupLinkerArgument ("--generate-warning-suppressions", "cs")] + public class CanGenerateWarningSuppressionFileCSharp { public static void Main () { @@ -36,7 +36,7 @@ class Warnings [Kept] public static Type TriggerUnrecognizedPattern () { - return typeof (CanGenerateWarningSuppressionFile); + return typeof (CanGenerateWarningSuppressionFileCSharp); } [Kept] diff --git a/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/CanGenerateWarningSuppressionFileXml.cs b/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/CanGenerateWarningSuppressionFileXml.cs new file mode 100644 index 000000000000..b0bb6f72e74d --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/CanGenerateWarningSuppressionFileXml.cs @@ -0,0 +1,24 @@ +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Text; + +namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression +{ + [SetupLinkerCoreAction ("skip")] + [SetupCompileBefore ("library.dll", new[] { "Dependencies/TriggerWarnings_Lib.cs" })] + [KeptAssembly ("library.dll")] + [SetupLinkerAction ("link", "library.dll")] + [SetupLinkerArgument ("--verbose")] + [SetupLinkerArgument ("--generate-warning-suppressions", "xml")] + public class CanGenerateWarningSuppressionFileXml + { + public static void Main () + { + TriggerWarnings_Lib.Main (); + } + } +} diff --git a/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/Dependencies/TriggerWarnings_Lib.cs b/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/Dependencies/TriggerWarnings_Lib.cs index 9586d18bad01..808427bc9414 100644 --- a/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/Dependencies/TriggerWarnings_Lib.cs +++ b/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/Dependencies/TriggerWarnings_Lib.cs @@ -7,14 +7,44 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies { public class TriggerWarnings_Lib { - public static Type UnrecognizedPattern () + public static void Main () + { + Expression.Call (TriggerUnrecognizedPattern (), "", Type.EmptyTypes); + Warning1 (); + var getProperty = Warning2; + NestedType.Warning3 (); + var list = new List (); + NestedType.Warning4 (ref list); + } + + public static Type TriggerUnrecognizedPattern () { return typeof (TriggerWarnings_Lib); } - public static void Main () + public static void Warning1 () { - Expression.Call (UnrecognizedPattern (), "", Type.EmptyTypes); + Expression.Call (TriggerUnrecognizedPattern (), "", Type.EmptyTypes); + } + + public static int Warning2 { + get { + Expression.Call (TriggerUnrecognizedPattern (), "", Type.EmptyTypes); + return 0; + } + } + + public class NestedType + { + public static void Warning3 () + { + Expression.Call (TriggerUnrecognizedPattern (), "", Type.EmptyTypes); + } + + public static void Warning4 (ref List p) + { + Expression.Call (TriggerUnrecognizedPattern (), "", Type.EmptyTypes); + } } } } diff --git a/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsUsingTargetViaXml.cs b/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsUsingTargetViaXml.cs new file mode 100644 index 000000000000..17e4c02a8ef8 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsUsingTargetViaXml.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies; + +namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression +{ + [SetupLinkAttributesFile ("SuppressWarningsUsingTargetViaXml.xml")] + [SetupCompileBefore ("library.dll", new[] { "Dependencies/TriggerWarnings_Lib.cs" })] + [KeptAssembly ("library.dll")] + [SetupLinkerAction ("link", "library.dll")] + [LogDoesNotContain ("TriggerUnrecognizedPattern()")] + public class SuppressWarningsUsingTargetViaXml + { + public static void Main () + { + TriggerWarnings_Lib.Main (); + } + } +} diff --git a/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsUsingTargetViaXml.xml b/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsUsingTargetViaXml.xml new file mode 100644 index 000000000000..d8cf0bfd04ae --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsUsingTargetViaXml.xml @@ -0,0 +1,35 @@ + + + + + ILLink + IL2006 + member + M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.Main + + + ILLink + IL2006 + member + M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.NestedType.Warning3 + + + ILLink + IL2006 + member + M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.NestedType.Warning4``1(System.Collections.Generic.List{``0}@) + + + ILLink + IL2006 + member + M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.Warning1 + + + ILLink + IL2006 + member + M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.get_Warning2 + + + \ No newline at end of file diff --git a/test/Mono.Linker.Tests/TestCases/Dependencies/WarningSuppressionExpectations1.cs b/test/Mono.Linker.Tests/TestCases/Dependencies/WarningSuppressionExpectations1.cs index aca59650fd84..ffb57f2c5f87 100644 --- a/test/Mono.Linker.Tests/TestCases/Dependencies/WarningSuppressionExpectations1.cs +++ b/test/Mono.Linker.Tests/TestCases/Dependencies/WarningSuppressionExpectations1.cs @@ -1,6 +1,6 @@ using System.Diagnostics.CodeAnalysis; +[assembly: UnconditionalSuppressMessage ("ILLink", "IL2006", Scope = "member", Target = "M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Warnings.get_Warning2")] [assembly: UnconditionalSuppressMessage ("ILLink", "IL2006", Scope = "member", Target = "M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Warnings.NestedType.Warning3")] [assembly: UnconditionalSuppressMessage ("ILLink", "IL2006", Scope = "member", Target = "M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Warnings.NestedType.Warning4``1(System.Collections.Generic.List{``0}@)")] [assembly: UnconditionalSuppressMessage ("ILLink", "IL2006", Scope = "member", Target = "M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Warnings.Warning1")] -[assembly: UnconditionalSuppressMessage ("ILLink", "IL2006", Scope = "member", Target = "M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Warnings.get_Warning2")] diff --git a/test/Mono.Linker.Tests/TestCases/Dependencies/WarningSuppressionExpectations2.cs b/test/Mono.Linker.Tests/TestCases/Dependencies/WarningSuppressionExpectations2.cs index 3f70dd6530fe..c5044a3650c2 100644 --- a/test/Mono.Linker.Tests/TestCases/Dependencies/WarningSuppressionExpectations2.cs +++ b/test/Mono.Linker.Tests/TestCases/Dependencies/WarningSuppressionExpectations2.cs @@ -1,3 +1,7 @@ using System.Diagnostics.CodeAnalysis; +[assembly: UnconditionalSuppressMessage ("ILLink", "IL2006", Scope = "member", Target = "M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.get_Warning2")] [assembly: UnconditionalSuppressMessage ("ILLink", "IL2006", Scope = "member", Target = "M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.Main")] +[assembly: UnconditionalSuppressMessage ("ILLink", "IL2006", Scope = "member", Target = "M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.NestedType.Warning3")] +[assembly: UnconditionalSuppressMessage ("ILLink", "IL2006", Scope = "member", Target = "M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.NestedType.Warning4``1(System.Collections.Generic.List{``0}@)")] +[assembly: UnconditionalSuppressMessage ("ILLink", "IL2006", Scope = "member", Target = "M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.Warning1")] diff --git a/test/Mono.Linker.Tests/TestCases/Dependencies/WarningSuppressionExpectations3.xml b/test/Mono.Linker.Tests/TestCases/Dependencies/WarningSuppressionExpectations3.xml new file mode 100644 index 000000000000..eea6cbf6ad9a --- /dev/null +++ b/test/Mono.Linker.Tests/TestCases/Dependencies/WarningSuppressionExpectations3.xml @@ -0,0 +1,35 @@ + + + + + ILLink + IL2006 + member + M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.get_Warning2 + + + ILLink + IL2006 + member + M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.Main + + + ILLink + IL2006 + member + M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.NestedType.Warning3 + + + ILLink + IL2006 + member + M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.NestedType.Warning4``1(System.Collections.Generic.List{``0}@) + + + ILLink + IL2006 + member + M:Mono.Linker.Tests.Cases.Warnings.WarningSuppression.Dependencies.TriggerWarnings_Lib.Warning1 + + + \ No newline at end of file diff --git a/test/Mono.Linker.Tests/TestCases/IndividualTests.cs b/test/Mono.Linker.Tests/TestCases/IndividualTests.cs index da377b9b70fd..338eff3f8158 100644 --- a/test/Mono.Linker.Tests/TestCases/IndividualTests.cs +++ b/test/Mono.Linker.Tests/TestCases/IndividualTests.cs @@ -58,9 +58,9 @@ public void CanOutputPInvokes () } [Test] - public void CanGenerateWarningSuppressionFile () + public void CanGenerateWarningSuppressionFileCSharp () { - var testcase = CreateIndividualCase (typeof (CanGenerateWarningSuppressionFile)); + var testcase = CreateIndividualCase (typeof (CanGenerateWarningSuppressionFileCSharp)); var result = Run (testcase); string[] expectedAssemblies = new string[] { "test", "library" }; @@ -74,6 +74,19 @@ public void CanGenerateWarningSuppressionFile () } } + [Test] + public void CanGenerateWarningSuppressionFileXml () + { + var testcase = CreateIndividualCase (typeof (CanGenerateWarningSuppressionFileXml)); + var result = Run (testcase); + var outputPath = result.OutputAssemblyPath.Parent.Combine ("library.WarningSuppressions.xml"); + if (!outputPath.Exists ()) + Assert.Fail ($"An XML file with a list of UnconditionalSuppressMessage attributes was expected to exist at {outputPath}"); + + Assert.IsTrue (File.ReadAllLines (outputPath).SequenceEqual ( + File.ReadAllLines (TestsDirectory.Combine ($"TestCases/Dependencies/WarningSuppressionExpectations3.xml")))); + } + [Test] public void CanEnableDependenciesDump () {