From c2b74e13bf95613677976e3ce9aac63a086bdd16 Mon Sep 17 00:00:00 2001 From: Connie Yau Date: Wed, 31 Jan 2018 08:26:11 -0800 Subject: [PATCH 1/3] Fixing CA3053 XmlResolver issue (#566) --- src/Microsoft.Fx.Portability/TargetMapper.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Fx.Portability/TargetMapper.cs b/src/Microsoft.Fx.Portability/TargetMapper.cs index 72bc4b032..5d08de394 100644 --- a/src/Microsoft.Fx.Portability/TargetMapper.cs +++ b/src/Microsoft.Fx.Portability/TargetMapper.cs @@ -84,11 +84,6 @@ public void Load(Stream stream) Load(stream, null); } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security.Xml", "CA3053:UseXmlSecureResolver", - Justification = @"For the call to XmlReader.Create() below, CA3053 recommends setting the -XmlReaderSettings.XmlResolver property to either null or an instance of XmlSecureResolver. -However, the said XmlResolver property no longer exists in .NET portable framework (i.e. core framework) which means there is no way to set it. -So we suppress this error until the reporting for CA3053 has been updated to account for .NET portable framework.")] private void Load(Stream stream, string path) { var readerSettings = new XmlReaderSettings @@ -97,6 +92,10 @@ private void Load(Stream stream, string path) CloseInput = false, IgnoreComments = true, IgnoreWhitespace = true, + DtdProcessing = DtdProcessing.Prohibit, +#if NET46 + XmlResolver = null +#endif }; try From 30fbba1536cf43752a6e73ba2bb07964cd7a8b33 Mon Sep 17 00:00:00 2001 From: Connie Yau Date: Wed, 31 Jan 2018 10:14:48 -0800 Subject: [PATCH 2/3] Fixing more FxCop issues (#569) * For each FormattableString, specify a culture or invariant * Suppress CA3053 because of the false positives --- src/ApiPort.VisualStudio.2015/ProjectBuilder2015.cs | 7 +++---- src/ApiPort.VisualStudio.Common/ComProjectMapper.cs | 9 +++++---- .../DefaultProjectBuilder.cs | 9 +++++---- src/ApiPort/DocIdSearchRepl.cs | 9 +++++---- .../HtmlReportWriter.cs | 5 +++-- .../Microsoft.Fx.Portability.csproj | 2 ++ src/Microsoft.Fx.Portability/TargetMapper.cs | 6 +++++- .../Utils/FormattableStringHelper.cs | 13 +++++++++++++ 8 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 src/Microsoft.Fx.Portability/Utils/FormattableStringHelper.cs diff --git a/src/ApiPort.VisualStudio.2015/ProjectBuilder2015.cs b/src/ApiPort.VisualStudio.2015/ProjectBuilder2015.cs index ab846acc8..43ec8c5f1 100644 --- a/src/ApiPort.VisualStudio.2015/ProjectBuilder2015.cs +++ b/src/ApiPort.VisualStudio.2015/ProjectBuilder2015.cs @@ -5,17 +5,16 @@ using ApiPortVS.Contracts; using EnvDTE; using Microsoft.VisualStudio.ProjectSystem; -using Microsoft.VisualStudio.ProjectSystem.Build; using Microsoft.VisualStudio.ProjectSystem.Designers; using Microsoft.VisualStudio.ProjectSystem.Utilities; using Microsoft.VisualStudio.Shell.Interop; using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; +using static Microsoft.Fx.Portability.Utils.FormattableStringHelper; namespace ApiPortVS.VS2015 { @@ -57,7 +56,7 @@ public ProjectBuilder2015(IVsSolutionBuildManager2 buildManager, IVSThreadingSer /// project is not a CPS project. private async Task> GetBuildOutputFilesFromCPSAsync( Project project, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken = default) { if (project == null) { @@ -68,7 +67,7 @@ private async Task> GetBuildOutputFilesFromCPSAsync( if (hierarchy == null) { - Trace.TraceWarning($"Unable to locate {nameof(IVsHierarchy)} for {project.Name}"); + Trace.TraceWarning(ToCurrentCulture($"Unable to locate {nameof(IVsHierarchy)} for {project.Name}")); return null; } diff --git a/src/ApiPort.VisualStudio.Common/ComProjectMapper.cs b/src/ApiPort.VisualStudio.Common/ComProjectMapper.cs index b00190a46..411575cde 100644 --- a/src/ApiPort.VisualStudio.Common/ComProjectMapper.cs +++ b/src/ApiPort.VisualStudio.Common/ComProjectMapper.cs @@ -9,6 +9,7 @@ using System.Diagnostics; using System.Threading.Tasks; using VisualStudio = Microsoft.VisualStudio.Shell; +using static Microsoft.Fx.Portability.Utils.FormattableStringHelper; namespace ApiPortVS { @@ -67,18 +68,18 @@ public async Task GetVsProjectConfigurationAsync(Project project) if (getConfigurationProvider == null) { - Trace.TraceError($"Could not retrieve {nameof(IVsGetCfgProvider)} from project: {project.Name}"); + Trace.TraceError(ToCurrentCulture($"Could not retrieve {nameof(IVsGetCfgProvider)} from project: {project.Name}")); return null; } if (ErrorHandler.Failed(getConfigurationProvider.GetCfgProvider(out IVsCfgProvider provider))) { - Trace.TraceError($"Could not retrieve {nameof(IVsCfgProvider)} from project: {project.Name}"); + Trace.TraceError(ToCurrentCulture($"Could not retrieve {nameof(IVsCfgProvider)} from project: {project.Name}")); return null; } if (!(provider is IVsCfgProvider2)) { - Trace.TraceError($"IVsCfgProvider returned {provider.GetType()} is not of the right type. Expected: {nameof(IVsCfgProvider2)}"); + Trace.TraceError(ToCurrentCulture($"IVsCfgProvider returned {provider.GetType()} is not of the right type. Expected: {nameof(IVsCfgProvider2)}")); return null; } @@ -87,7 +88,7 @@ public async Task GetVsProjectConfigurationAsync(Project project) if (ErrorHandler.Failed(provider2.GetCfgOfName(activeConfiguration.ConfigurationName, activeConfiguration.PlatformName, out IVsCfg configuration))) { - Trace.TraceError($"Could not retrieve {nameof(IVsCfg)} from project: {project.Name}"); + Trace.TraceError(ToCurrentCulture($"Could not retrieve {nameof(IVsCfg)} from project: {project.Name}")); return null; } diff --git a/src/ApiPort.VisualStudio.Common/DefaultProjectBuilder.cs b/src/ApiPort.VisualStudio.Common/DefaultProjectBuilder.cs index ea1c4e6e3..eef4be0c8 100644 --- a/src/ApiPort.VisualStudio.Common/DefaultProjectBuilder.cs +++ b/src/ApiPort.VisualStudio.Common/DefaultProjectBuilder.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using static Microsoft.VisualStudio.VSConstants; +using static Microsoft.Fx.Portability.Utils.FormattableStringHelper; using System; using System.Threading; using Microsoft.VisualStudio; @@ -99,7 +100,7 @@ public virtual async Task BuildAsync(IEnumerable projects) if (!(configuration is IVsProjectCfg2 configuration2)) { - Trace.TraceError($"IVsCfg returned {configuration.GetType()} is not of the right type. Expected: {nameof(IVsProjectCfg2)}"); + Trace.TraceError(ToCurrentCulture($"IVsCfg returned {configuration.GetType()} is not of the right type. Expected: {nameof(IVsProjectCfg2)}")); return null; } @@ -107,19 +108,19 @@ public virtual async Task BuildAsync(IEnumerable projects) if (ErrorHandler.Failed(configuration2.OpenOutputGroup(Common.Constants.OutputGroups.BuiltProject, out IVsOutputGroup outputGroup))) { - Trace.TraceError($"Could not retrieve {nameof(IVsOutputGroup)} from project: {project.Name}"); + Trace.TraceError(ToCurrentCulture($"Could not retrieve {nameof(IVsOutputGroup)} from project: {project.Name}")); return null; } if (!(outputGroup is IVsOutputGroup2 outputGroup2)) { - Trace.TraceError($"Could not retrieve {nameof(IVsOutputGroup2)} from project: {project.Name}"); + Trace.TraceError(ToCurrentCulture($"Could not retrieve {nameof(IVsOutputGroup2)} from project: {project.Name}")); return null; } if (ErrorHandler.Failed(outputGroup2.get_KeyOutputObject(out IVsOutput2 keyGroup))) { - Trace.TraceError($"Could not retrieve {nameof(IVsOutput2)} from project: {project.Name}"); + Trace.TraceError(ToCurrentCulture($"Could not retrieve {nameof(IVsOutput2)} from project: {project.Name}")); return null; } diff --git a/src/ApiPort/DocIdSearchRepl.cs b/src/ApiPort/DocIdSearchRepl.cs index 9e3f26aa2..03af7639d 100644 --- a/src/ApiPort/DocIdSearchRepl.cs +++ b/src/ApiPort/DocIdSearchRepl.cs @@ -7,6 +7,7 @@ using System.Globalization; using System.Linq; using System.Threading.Tasks; +using static Microsoft.Fx.Portability.Utils.FormattableStringHelper; namespace ApiPort { @@ -20,15 +21,15 @@ public DocIdSearchRepl(ISearcher searcher) public async Task DocIdSearchAsync() { - var countOption = $"{LocalizedStrings.ReplOptionCount}[{LocalizedStrings.Number}]"; + var countOption = ToCurrentCulture($"{LocalizedStrings.ReplOptionCount}[{LocalizedStrings.Number}]"); var optionColumnWidth = Math.Max(countOption.Length, LocalizedStrings.ReplOptionExit.Length); Console.WriteLine(); Console.WriteLine(LocalizedStrings.ReplEnterQuery); Console.WriteLine(); Console.WriteLine(LocalizedStrings.ReplOptionsHeader); - Console.WriteLine($" {LocalizedStrings.ReplOptionExit.PadRight(optionColumnWidth)}\t{LocalizedStrings.ReplOptionExit_Text}"); - Console.WriteLine($" {countOption.PadRight(optionColumnWidth)}\t{LocalizedStrings.ReplOptionCount_Text}"); + Console.WriteLine(ToCurrentCulture($" {LocalizedStrings.ReplOptionExit.PadRight(optionColumnWidth)}\t{LocalizedStrings.ReplOptionExit_Text}")); + Console.WriteLine(ToCurrentCulture($" {countOption.PadRight(optionColumnWidth)}\t{LocalizedStrings.ReplOptionCount_Text}")); Console.WriteLine(); Console.CancelKeyPress += ConsoleCancelKeyPress; @@ -95,7 +96,7 @@ private async Task ReplLoopAsync() { foreach (var result in results) { - WriteColorLine($"\"{result}\",", ConsoleColor.Cyan); + WriteColorLine(ToCurrentCulture($"\"{result}\","), ConsoleColor.Cyan); } } else diff --git a/src/Microsoft.Fx.Portability.Reports.Html/HtmlReportWriter.cs b/src/Microsoft.Fx.Portability.Reports.Html/HtmlReportWriter.cs index eca634077..6f07205b3 100644 --- a/src/Microsoft.Fx.Portability.Reports.Html/HtmlReportWriter.cs +++ b/src/Microsoft.Fx.Portability.Reports.Html/HtmlReportWriter.cs @@ -12,6 +12,7 @@ using System; using Microsoft.Fx.Portability.Reports.Html; using Microsoft.Fx.Portability.Reports.Html.Resources; +using static System.FormattableString; namespace Microsoft.Fx.Portability.Reports { @@ -115,7 +116,7 @@ public IEncodedString TargetSupportCell(TargetSupportedIn supportStatus) var className = supported ? "IconSuccessEncoded" : "IconErrorEncoded"; var title = supported ? LocalizedStrings.Supported : LocalizedStrings.NotSupported; - return Raw($""); + return Raw(Invariant($"")); } public IEncodedString BreakingChangeCountCell(int breaks, int warningThreshold, int errorThreshold) @@ -130,7 +131,7 @@ public IEncodedString BreakingChangeCountCell(int breaks, int warningThreshold, className = breaks <= errorThreshold ? "FewBreakingChanges" : "ManyBreakingChanges"; } - return Raw($"{breaks}"); + return Raw(Invariant($"{breaks}")); } #pragma warning restore CA1822 // Mark members as static } diff --git a/src/Microsoft.Fx.Portability/Microsoft.Fx.Portability.csproj b/src/Microsoft.Fx.Portability/Microsoft.Fx.Portability.csproj index a4e0cdaec..dc733f041 100644 --- a/src/Microsoft.Fx.Portability/Microsoft.Fx.Portability.csproj +++ b/src/Microsoft.Fx.Portability/Microsoft.Fx.Portability.csproj @@ -7,6 +7,8 @@ --> netstandard1.3;net46 The core data structures and network calls for .NET Portability Analyzer + + $(DefineConstants);CODE_ANALYSIS diff --git a/src/Microsoft.Fx.Portability/TargetMapper.cs b/src/Microsoft.Fx.Portability/TargetMapper.cs index 5d08de394..6acd716a7 100644 --- a/src/Microsoft.Fx.Portability/TargetMapper.cs +++ b/src/Microsoft.Fx.Portability/TargetMapper.cs @@ -84,6 +84,8 @@ public void Load(Stream stream) Load(stream, null); } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security.Xml", "CA3053:UseXmlSecureResolver", + Justification = @"We have set this in line 99 and 115. This is a false positive. https://msdn.microsoft.com/en-us/library/mt661872.aspx")] private void Load(Stream stream, string path) { var readerSettings = new XmlReaderSettings @@ -113,7 +115,9 @@ private void Load(Stream stream, string path) XmlResolver = null }; - schemas.Add(null, XmlReader.Create(xsdStream, xmlReaderSettings)); + var reader = XmlReader.Create(xsdStream, xmlReaderSettings); + + schemas.Add(null, reader); doc.Validate(schemas, (s, e) => { throw new TargetMapperException(e.Message, e.Exception); }); } #endif diff --git a/src/Microsoft.Fx.Portability/Utils/FormattableStringHelper.cs b/src/Microsoft.Fx.Portability/Utils/FormattableStringHelper.cs new file mode 100644 index 000000000..96e04fd20 --- /dev/null +++ b/src/Microsoft.Fx.Portability/Utils/FormattableStringHelper.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Globalization; + +namespace Microsoft.Fx.Portability.Utils +{ + public static class FormattableStringHelper + { + public static string ToCurrentCulture(FormattableString formattableString) => formattableString.ToString(CultureInfo.CurrentCulture); + } +} From d0a5683d2c3fba8902a99bcfd8e67f70f5c42a7b Mon Sep 17 00:00:00 2001 From: Connie Yau Date: Wed, 31 Jan 2018 10:32:24 -0800 Subject: [PATCH 3/3] Fix globalisation issues with ProjectBuilder2017 --- ...ctBuilder2015.cs => ProjectBuilder2017.cs} | 33 +++++++++---------- .../ServiceProvider.cs | 2 +- 2 files changed, 17 insertions(+), 18 deletions(-) rename src/ApiPort.VisualStudio.2017/{ProjectBuilder2015.cs => ProjectBuilder2017.cs} (90%) diff --git a/src/ApiPort.VisualStudio.2017/ProjectBuilder2015.cs b/src/ApiPort.VisualStudio.2017/ProjectBuilder2017.cs similarity index 90% rename from src/ApiPort.VisualStudio.2017/ProjectBuilder2015.cs rename to src/ApiPort.VisualStudio.2017/ProjectBuilder2017.cs index dadbf36e8..1d41859b2 100644 --- a/src/ApiPort.VisualStudio.2017/ProjectBuilder2015.cs +++ b/src/ApiPort.VisualStudio.2017/ProjectBuilder2017.cs @@ -1,28 +1,27 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using ApiPortVS.Common; using ApiPortVS.Contracts; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using EnvDTE; -using Microsoft.VisualStudio.Shell.Interop; -using System.Threading; -using ApiPortVS.Common; -using System.Diagnostics; using Microsoft.VisualStudio.ProjectSystem; +using Microsoft.VisualStudio.ProjectSystem.Build; using Microsoft.VisualStudio.ProjectSystem.Properties; -using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell.Interop; +using System; using System.Collections.Concurrent; -using Microsoft.VisualStudio.ProjectSystem.Build; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using static Microsoft.Fx.Portability.Utils.FormattableStringHelper; namespace ApiPortVS.VS2017 { - public class ProjectBuilder2015 : DefaultProjectBuilder + public class ProjectBuilder2017 : DefaultProjectBuilder { - public ProjectBuilder2015( + public ProjectBuilder2017( IVsSolutionBuildManager2 buildManager, IVSThreadingService threadingService, IProjectMapper projectMapper) @@ -36,7 +35,7 @@ public ProjectBuilder2015( /// https://github.com/Microsoft/visualfsharp/blob/master/vsintegration/tests/unittests/Tests.ProjectSystem.Miscellaneous.fs#L168-L182 /// /// null if it is unable to retrieve VS configuration objects - public override async Task> GetBuildOutputFilesAsync(Project project, CancellationToken cancellationToken = default(CancellationToken)) + public override async Task> GetBuildOutputFilesAsync(Project project, CancellationToken cancellationToken = default) { if (project == null) { @@ -61,7 +60,7 @@ public ProjectBuilder2015( /// project is not a CPS project. private async Task> GetBuildOutputFilesFromCPSAsync( Project project, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken = default) { if (project == null) { @@ -72,7 +71,7 @@ private async Task> GetBuildOutputFilesFromCPSAsync( if (hierarchy == null) { - Trace.TraceWarning($"Unable to locate {nameof(IVsHierarchy)} for {project.Name}"); + Trace.TraceWarning(ToCurrentCulture($"Unable to locate {nameof(IVsHierarchy)} for {project.Name}")); return null; } @@ -110,7 +109,7 @@ private async Task> GetBuildOutputFilesFromCPSAsync( } catch (Exception e) { - Trace.TraceError($"Could not fetch key output from project configuration {proj.ProjectConfiguration.Name}. Exception: {e}", e); + Trace.TraceError(ToCurrentCulture($"Could not fetch key output from project configuration {proj.ProjectConfiguration.Name}. Exception: {e}"), e); } } } diff --git a/src/ApiPort.VisualStudio.2017/ServiceProvider.cs b/src/ApiPort.VisualStudio.2017/ServiceProvider.cs index 946e65f43..d47b09806 100644 --- a/src/ApiPort.VisualStudio.2017/ServiceProvider.cs +++ b/src/ApiPort.VisualStudio.2017/ServiceProvider.cs @@ -24,7 +24,7 @@ protected override void Load(ContainerBuilder builder) builder.RegisterType() .As() .SingleInstance(); - builder.RegisterType() + builder.RegisterType() .As() .SingleInstance(); }