From 53c4c6cbb8e004661a8cad5f9735cd74b416deb6 Mon Sep 17 00:00:00 2001 From: ryanbodrug-microsoft <56318517+ryanbodrug-microsoft@users.noreply.github.com> Date: Thu, 23 Jul 2020 16:05:36 -0700 Subject: [PATCH] User/ryanbod/folders enable staticanalysis (#5137) * Enabling static analysis and settings treat warnings as errors * Fixing/Supressing static analysis warnings in ContextmenuLoader and removing unused code * Fixing static analysis errors in Main.cs * Fixing static analysis warnings for folderpluginSettings.xaml.cs --- .../ContextMenuLoader.cs | 36 ++--------- .../FolderPluginSettings.xaml.cs | 62 +++++++++--------- .../Plugins/Microsoft.Plugin.Folder/Main.cs | 64 ++++++++++++------- .../Microsoft.Plugin.Folder.csproj | 5 ++ .../Microsoft.Plugin.Folder/Settings.cs | 4 +- 5 files changed, 81 insertions(+), 90 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/ContextMenuLoader.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/ContextMenuLoader.cs index 87c15f17fd..43e36f08c4 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/ContextMenuLoader.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/ContextMenuLoader.cs @@ -21,8 +21,9 @@ namespace Microsoft.Plugin.Folder public ContextMenuLoader(PluginInitContext context) { _context = context; - } - + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "We want to keep the process alive, and instead log the exception")] public List LoadContextMenus(Result selectedResult) { var contextMenus = new List(); @@ -95,6 +96,7 @@ namespace Microsoft.Plugin.Folder return contextMenus; } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "We want to keep the process alive, and instead log the exception")] private ContextMenuResult CreateOpenContainingFolderResult(SearchResult record) { return new ContextMenuResult @@ -124,35 +126,7 @@ namespace Microsoft.Plugin.Folder }; } - - private Result CreateOpenWithEditorResult(SearchResult record) - { - string editorPath = "notepad.exe"; // TODO add the ability to create a custom editor - - var name = "Open With Editor: " + Path.GetFileNameWithoutExtension(editorPath); - return new Result - { - Title = name, - Action = _ => - { - try - { - Process.Start(editorPath, record.FullPath); - return true; - } - catch (Exception e) - { - var message = $"Fail to editor for file at {record.FullPath}"; - LogException(message, e); - _context.API.ShowMsg(message); - return false; - } - }, - IcoPath = editorPath - }; - } - - public void LogException(string message, Exception e) + public static void LogException(string message, Exception e) { Log.Exception($"|Microsoft.Plugin.Folder.ContextMenu|{message}", e); } diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/FolderPluginSettings.xaml.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/FolderPluginSettings.xaml.cs index d52c40bdc0..e7b75b7b91 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/FolderPluginSettings.xaml.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/FolderPluginSettings.xaml.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Windows; @@ -15,13 +17,13 @@ namespace Microsoft.Plugin.Folder public partial class FileSystemSettings { private IPublicAPI woxAPI; - private Settings _settings; + private FolderSettings _settings; - public FileSystemSettings(IPublicAPI woxAPI, Settings settings) + public FileSystemSettings(IPublicAPI woxAPI, FolderSettings settings) { this.woxAPI = woxAPI; InitializeComponent(); - _settings = settings; + _settings = settings ?? throw new ArgumentNullException(paramName:nameof(settings)); lbxFolders.ItemsSource = _settings.FolderLinks; } @@ -30,7 +32,7 @@ namespace Microsoft.Plugin.Folder var selectedFolder = lbxFolders.SelectedItem as FolderLink; if (selectedFolder != null) { - string msg = string.Format(woxAPI.GetTranslation("wox_plugin_folder_delete_folder_link"), selectedFolder.Path); + string msg = string.Format(CultureInfo.InvariantCulture, woxAPI.GetTranslation("wox_plugin_folder_delete_folder_link"), selectedFolder.Path); if (MessageBox.Show(msg, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes) { @@ -50,15 +52,17 @@ namespace Microsoft.Plugin.Folder var selectedFolder = lbxFolders.SelectedItem as FolderLink; if (selectedFolder != null) { - var folderBrowserDialog = new FolderBrowserDialog(); - folderBrowserDialog.SelectedPath = selectedFolder.Path; - if (folderBrowserDialog.ShowDialog() == DialogResult.OK) - { - var link = _settings.FolderLinks.First(x => x.Path == selectedFolder.Path); - link.Path = folderBrowserDialog.SelectedPath; - } + using (var folderBrowserDialog = new FolderBrowserDialog()) + { + folderBrowserDialog.SelectedPath = selectedFolder.Path; + if (folderBrowserDialog.ShowDialog() == DialogResult.OK) + { + var link = _settings.FolderLinks.First(x => x.Path == selectedFolder.Path); + link.Path = folderBrowserDialog.SelectedPath; + } - lbxFolders.Items.Refresh(); + lbxFolders.Items.Refresh(); + } } else { @@ -69,36 +73,28 @@ namespace Microsoft.Plugin.Folder private void btnAdd_Click(object sender, RoutedEventArgs e) { - var folderBrowserDialog = new FolderBrowserDialog(); - if (folderBrowserDialog.ShowDialog() == DialogResult.OK) - { - var newFolder = new FolderLink - { - Path = folderBrowserDialog.SelectedPath - }; - - if (_settings.FolderLinks == null) - { - _settings.FolderLinks = new List(); + using (var folderBrowserDialog = new FolderBrowserDialog()) + { + if (folderBrowserDialog.ShowDialog() == DialogResult.OK) + { + var newFolder = new FolderLink + { + Path = folderBrowserDialog.SelectedPath + }; + + _settings.FolderLinks.Add(newFolder); } - _settings.FolderLinks.Add(newFolder); + lbxFolders.Items.Refresh(); } - - lbxFolders.Items.Refresh(); } private void lbxFolders_Drop(object sender, DragEventArgs e) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); - if (files != null && files.Count() > 0) + if (files != null && files.Any()) { - if (_settings.FolderLinks == null) - { - _settings.FolderLinks = new List(); - } - foreach (string s in files) { if (Directory.Exists(s)) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Main.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Main.cs index 8adc5105cb..04a8b9b794 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Main.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Main.cs @@ -2,6 +2,7 @@ using Microsoft.PowerToys.Settings.UI.Lib; using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Linq; using System.Text.RegularExpressions; @@ -24,13 +25,13 @@ namespace Microsoft.Plugin.Folder private static List _driverNames; private PluginInitContext _context; - private readonly Settings _settings; - private readonly PluginJsonStorage _storage; + private readonly FolderSettings _settings; + private readonly PluginJsonStorage _storage; private IContextMenu _contextMenuLoader; public Main() { - _storage = new PluginJsonStorage(); + _storage = new PluginJsonStorage(); _settings = _storage.Load(); } @@ -49,13 +50,19 @@ namespace Microsoft.Plugin.Folder _context = context; _contextMenuLoader = new ContextMenuLoader(context); InitialDriverList(); - } - + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase", Justification = "Do not want to change the behavior of the application, but want to enforce static analysis")] public List Query(Query query) { + if(query == null) + { + throw new ArgumentNullException(paramName: nameof(query)); + } + var results = GetUserFolderResults(query); - string search = query.Search.ToLower(); + string search = query.Search.ToLower(CultureInfo.InvariantCulture); if (!IsDriveOrSharedFolder(search)) return results; @@ -72,7 +79,7 @@ namespace Microsoft.Plugin.Folder private static bool IsDriveOrSharedFolder(string search) { - if (search.StartsWith(@"\\")) + if (search.StartsWith(@"\\", StringComparison.InvariantCulture)) { // share folder return true; } @@ -90,7 +97,7 @@ namespace Microsoft.Plugin.Folder return false; } - private Result CreateFolderResult(string title, string subtitle, string path, Query query) + private static Result CreateFolderResult(string title, string subtitle, string path, Query query) { return new Result { @@ -106,18 +113,25 @@ namespace Microsoft.Plugin.Folder return true; } }; - } - + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase", Justification = "Do not want to change the behavior of the application, but want to enforce static analysis")] private List GetUserFolderResults(Query query) { - string search = query.Search.ToLower(); + if(query == null) + { + throw new ArgumentNullException(paramName: nameof(query)); + } + + string search = query.Search.ToLower(CultureInfo.InvariantCulture); var userFolderLinks = _settings.FolderLinks.Where( x => x.Nickname.StartsWith(search, StringComparison.OrdinalIgnoreCase)); var results = userFolderLinks.Select(item => CreateFolderResult(item.Nickname, item.Path, item.Path, query)).ToList(); return results; - } - + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase", Justification = "Do not want to change the behavior of the application, but want to enforce static analysis")] private void InitialDriverList() { if (_driverNames == null) @@ -126,7 +140,7 @@ namespace Microsoft.Plugin.Folder var allDrives = DriveInfo.GetDrives(); foreach (DriveInfo driver in allDrives) { - _driverNames.Add(driver.Name.ToLower().TrimEnd('\\')); + _driverNames.Add(driver.Name.ToLower(CultureInfo.InvariantCulture).TrimEnd('\\')); } } } @@ -134,8 +148,9 @@ namespace Microsoft.Plugin.Folder private static readonly char[] _specialSearchChars = new char[] { '?', '*', '>' - }; - + }; + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase", Justification = "Do not want to change the behavior of the application, but want to enforce static analysis")] private List QueryInternal_Directory_Exists(Query query) { var search = query.Search; @@ -149,7 +164,7 @@ namespace Microsoft.Plugin.Folder int index = search.LastIndexOf('\\'); if (index > 0 && index < (search.Length - 1)) { - incompleteName = search.Substring(index + 1).ToLower(); + incompleteName = search.Substring(index + 1).ToLower(CultureInfo.InvariantCulture); search = search.Substring(0, index + 1); if (!Directory.Exists(search)) { @@ -164,19 +179,19 @@ namespace Microsoft.Plugin.Folder else { // folder exist, add \ at the end of doesn't exist - if (!search.EndsWith("\\")) + if (!search.EndsWith("\\", StringComparison.InvariantCulture)) { search += "\\"; } } - results.Add(CreateOpenCurrentFolderResult(incompleteName, search)); + results.Add(CreateOpenCurrentFolderResult( search)); var searchOption = SearchOption.TopDirectoryOnly; incompleteName += "*"; // give the ability to search all folder when starting with > - if (incompleteName.StartsWith(">")) + if (incompleteName.StartsWith(">", StringComparison.InvariantCulture)) { searchOption = SearchOption.AllDirectories; @@ -223,8 +238,9 @@ namespace Microsoft.Plugin.Folder // Initial ordering, this order can be updated later by UpdateResultView.MainViewModel based on history of user selection. return results.Concat(folderList.OrderBy(x => x.Title)).Concat(fileList.OrderBy(x => x.Title)).ToList(); - } - + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "We want to keep the process alve and instead inform the user of the error")] private static Result CreateFileResult(string filePath, Query query) { var result = new Result @@ -251,14 +267,14 @@ namespace Microsoft.Plugin.Folder return result; } - private static Result CreateOpenCurrentFolderResult(string incompleteName, string search) + private static Result CreateOpenCurrentFolderResult(string search) { var firstResult = "Open " + search; var folderName = search.TrimEnd('\\').Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None).Last(); var sanitizedPath = Regex.Replace(search, @"[\/\\]+", "\\"); // A network path must start with \\ - if (sanitizedPath.StartsWith("\\")) + if (sanitizedPath.StartsWith("\\", StringComparison.InvariantCulture)) { sanitizedPath = sanitizedPath.Insert(0, "\\"); } diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Microsoft.Plugin.Folder.csproj b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Microsoft.Plugin.Folder.csproj index fa32fc1a67..8b712f61ca 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Microsoft.Plugin.Folder.csproj +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Microsoft.Plugin.Folder.csproj @@ -23,6 +23,7 @@ MinimumRecommendedRules.ruleset 4 false + true @@ -94,6 +95,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Settings.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Settings.cs index 70b6aed4f5..beeea2a222 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Settings.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Settings.cs @@ -4,9 +4,9 @@ using Wox.Infrastructure.Storage; namespace Microsoft.Plugin.Folder { - public class Settings + public class FolderSettings { [JsonProperty] - public List FolderLinks { get; set; } = new List(); + public List FolderLinks { get;} = new List(); } }