diff --git a/src/CodeFormatter/App.config b/src/CodeFormatter/App.config index 1cc1bd15..f1cb1f67 100644 --- a/src/CodeFormatter/App.config +++ b/src/CodeFormatter/App.config @@ -7,15 +7,15 @@ - + - + - + @@ -23,7 +23,7 @@ - + @@ -31,11 +31,11 @@ - + - + diff --git a/src/CodeFormatter/BasicAnalyzerAssemblyLoader.cs b/src/CodeFormatter/BasicAnalyzerAssemblyLoader.cs new file mode 100644 index 00000000..8cbb17a0 --- /dev/null +++ b/src/CodeFormatter/BasicAnalyzerAssemblyLoader.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; + +namespace CodeFormatter +{ + public class BasicAnalyzerAssemblyLoader : IAnalyzerAssemblyLoader + { + private readonly Dictionary _pathsToAssemblies = new Dictionary(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _namesToAssemblies = new Dictionary(); + private readonly List _dependencyPaths = new List(); + + public void AddDependencyLocation(string fullPath) + { + if (fullPath == null) + { + throw new ArgumentNullException(nameof(fullPath)); + } + + if (!_dependencyPaths.Contains(fullPath, StringComparer.OrdinalIgnoreCase)) + { + _dependencyPaths.Add(fullPath); + } + } + + public Assembly LoadFromPath(string fullPath) + { + if (fullPath == null) + { + throw new ArgumentNullException(nameof(fullPath)); + } + + Assembly assembly; + if (_pathsToAssemblies.TryGetValue(fullPath, out assembly)) + { + return assembly; + } + else + { + assembly = Assembly.LoadFrom(fullPath); + _pathsToAssemblies[fullPath] = assembly; + _namesToAssemblies[assembly.FullName] = assembly; + return assembly; + } + } + } +} diff --git a/src/CodeFormatter/CodeFormatter.csproj b/src/CodeFormatter/CodeFormatter.csproj index 868ecd9c..65892f7a 100644 --- a/src/CodeFormatter/CodeFormatter.csproj +++ b/src/CodeFormatter/CodeFormatter.csproj @@ -21,32 +21,33 @@ ..\packages\CommandLineParser.2.0.273-beta\lib\net45\CommandLine.dll True - - ..\packages\Microsoft.CodeAnalysis.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.dll + + + ..\packages\Microsoft.CodeAnalysis.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True @@ -75,8 +76,8 @@ True - - ..\packages\System.Reflection.Metadata.1.1.0\lib\dotnet5.2\System.Reflection.Metadata.dll + + ..\packages\System.Reflection.Metadata.1.2.0-rc3-23811\lib\dotnet5.2\System.Reflection.Metadata.dll True @@ -86,6 +87,7 @@ + diff --git a/src/CodeFormatter/FormatOptions.cs b/src/CodeFormatter/FormatOptions.cs index b6555f88..15f73168 100644 --- a/src/CodeFormatter/FormatOptions.cs +++ b/src/CodeFormatter/FormatOptions.cs @@ -15,58 +15,98 @@ namespace CodeFormatter { - [Verb("format", HelpText = "Apply code formatting rules and analyzers to specified project.")] - internal class FormatOptions + internal class CommandLineOptions { [Value( 0, - HelpText = "Project, solution or response file to drive code formatting.", + HelpText = "Project, solution or response file to drive code formatting.", Required = true)] - public IEnumerable FormatTargets { get; set; } + public IEnumerable Targets { get; set; } [Option( 'o', "options-file-path", HelpText = "Path to an options file that should be used to configure analysis")] public string OptionsFilePath { get; set; } - + [Option( - "file-filters", - HelpText = "Only apply changes to files with specified name(s).", + "file-filters", + HelpText = "Only apply changes to files with specified name(s).", Separator = ',')] public IEnumerable FileFilters { get; set; } [Option( - 'l', "lang", + 'l', "lang", HelpText = "Specifies the language to use when a response file is specified, e.g., 'C#', 'Visual Basic', ... (default: 'C#').")] public string Language { get; set; } [Option( - 'c', "configs", - HelpText = "Comma-separated list of preprocessor configurations the formatter should run under.", + 'c', "configs", + HelpText = "Comma-separated list of preprocessor configurations the formatter should run under.", Separator = ',')] public IEnumerable PreprocessorConfigurations { get; set; } [Option( - "copyright", + "copyright", HelpText = "Specifies file containing copyright header.")] - public string CopyrightHeaderFile { get; set; } + public string CopyrightHeaderFile { get; set; } [Option( - 'v', "verbose", + 'v', "verbose", HelpText = "Verbose output.")] public bool Verbose { get; set; } [Option( - "define-dotnet_formatter", + "define-dotnet_formatter", HelpText = "Define DOTNET_FORMATTER in order to allow #if !DOTNET_FORMATTER constructs in code (to opt out of reformatting).")] public bool DefineDotNetFormatter { get; set; } - + [Option( "use-analyzers", HelpText = "TEMPORARY: invoke built-in analyzers rather than rules to perform reformatting.")] public bool UseAnalyzers { get; set; } + [Option( + "analyzer-list", + HelpText = "A file containing a newline separated list of analyzer assemblies to be run against the target source.")] + public string AnalyzerListFile { get; set; } + + [Option( + "log-output-path", + HelpText = "Path to a file where analysis or format results will be logged.")] + public string LogOutputPath { get; set; } + + public virtual bool ApplyFixes { get; } + + private ImmutableArray _analyzerListText; + public ImmutableArray AnalyzerListText + { + get + { + if (_analyzerListText == null) + { + _analyzerListText = InitializeAnalyzerListText(AnalyzerListFile); + } + return _analyzerListText; + } + internal set + { + _analyzerListText = value; + } + } + + private static ImmutableArray InitializeAnalyzerListText(string analyzerListFile) + { + ImmutableArray analyzerListText = new ImmutableArray(); + + if (!String.IsNullOrEmpty(analyzerListFile)) + { + analyzerListText = ImmutableArray.CreateRange(File.ReadAllLines(analyzerListFile)); + } + + return analyzerListText; + } + private ImmutableArray _copyrightHeaderText; public ImmutableArray CopyrightHeaderText { @@ -122,7 +162,7 @@ private ImmutableDictionary BuildRuleMapFromOptions() Debug.Assert(tokens.Length == 2); Debug.Assert(tokens[1].Equals("Enabled")); - string rule = tokens[0]; + string rule = tokens[0]; result[rule] = (bool)propertyBag[key]; } @@ -130,4 +170,16 @@ private ImmutableDictionary BuildRuleMapFromOptions() return _ruleMap; } } -} + + [Verb("format", HelpText = "Apply code formatting rules and analyzers to specified targets.")] + internal class FormatOptions : CommandLineOptions + { + public override bool ApplyFixes { get { return true; } } + } + + [Verb("analyze", HelpText = "Apply analyzers to specified targets but do not apply code fixes.")] + internal class AnalyzeOptions : CommandLineOptions + { + public override bool ApplyFixes { get { return false; } } + } +} \ No newline at end of file diff --git a/src/CodeFormatter/Program.cs b/src/CodeFormatter/Program.cs index 0e9c3505..1ca3ed8d 100644 --- a/src/CodeFormatter/Program.cs +++ b/src/CodeFormatter/Program.cs @@ -18,6 +18,7 @@ using Microsoft.DotNet.CodeFormatter.Analyzers; using Microsoft.CodeAnalysis.Options; using System.Diagnostics; +using Microsoft.CodeAnalysis.Diagnostics; namespace CodeFormatter { @@ -31,11 +32,13 @@ private static int Main(string[] args) return Parser.Default.ParseArguments< ListOptions, ExportOptions, - FormatOptions>(args) + FormatOptions, + AnalyzeOptions>(args) .MapResult( (ListOptions listOptions) => RunListCommand(listOptions), (ExportOptions exportOptions) => RunExportOptionsCommand(exportOptions), (FormatOptions formatOptions) => RunFormatCommand(formatOptions), + (AnalyzeOptions analyzeOptions) => RunAnalyzeCommand(analyzeOptions), errs => FAILED); } @@ -90,17 +93,28 @@ private static void ListRulesAndAnalyzers(bool listAnalyzers, bool listRules) } } } + private static int RunAnalyzeCommand(AnalyzeOptions options) + { + return RunCommand(options, false); + } private static int RunFormatCommand(FormatOptions options) { + return RunCommand(options, true); + } + + private static int RunCommand(CommandLineOptions options, bool applyCodeFixes) { var cts = new CancellationTokenSource(); var ct = cts.Token; Console.CancelKeyPress += delegate { cts.Cancel(); }; + var stopwatch = new Stopwatch(); + stopwatch.Start(); + try { - RunFormatAsync(options, ct).Wait(ct); + RunAsync(options, ct).Wait(ct); Console.WriteLine("Completed formatting."); return SUCCEEDED; } @@ -117,11 +131,28 @@ private static int RunFormatCommand(FormatOptions options) return FAILED; } + finally + { + stopwatch.Stop(); + Console.WriteLine("Total time: {0}", stopwatch.Elapsed); + } } - private static async Task RunFormatAsync(FormatOptions options, CancellationToken cancellationToken) + private static ImmutableArray LoadAnalyzersFromAssembly(string path, bool throwIfNoAnalyzersFound) { - var engine = FormattingEngine.Create(OptionsHelper.DefaultCompositionAssemblies); + var analyzerRef = new AnalyzerFileReference(path, new BasicAnalyzerAssemblyLoader()); + var newAnalyzers = analyzerRef.GetAnalyzersForAllLanguages(); + if (newAnalyzers.Count() == 0 && throwIfNoAnalyzersFound) + { + throw new Exception(String.Format("Specified analyzer assembly {0} contained no analyzers", analyzerRef.GetAssembly().FullName)); + } + return newAnalyzers; + } + + private static async Task RunAsync(CommandLineOptions options, CancellationToken cancellationToken) + { + var assemblies = OptionsHelper.DefaultCompositionAssemblies; + var engine = FormattingEngine.Create(assemblies); var configBuilder = ImmutableArray.CreateBuilder(); configBuilder.Add(options.PreprocessorConfigurations.ToArray()); @@ -132,7 +163,33 @@ private static async Task RunFormatAsync(FormatOptions options, Cancellatio engine.AllowTables = options.DefineDotNetFormatter; engine.FileNames = options.FileFilters.ToImmutableArray(); engine.CopyrightHeader = options.CopyrightHeaderText; + engine.ApplyFixes = options.ApplyFixes; + engine.LogOutputPath = options.LogOutputPath; + if (options.AnalyzerListFile != null && options.AnalyzerListText != null && options.AnalyzerListText.Count() > 0) + { + foreach (var analyzerPath in options.AnalyzerListText) + { + if (File.Exists(analyzerPath)) + { + var newAnalyzers = LoadAnalyzersFromAssembly(analyzerPath, true); + engine.AddAnalyzers(newAnalyzers); + } + else if (Directory.Exists(analyzerPath)) + { + var DLLs = Directory.GetFiles(analyzerPath, "*.dll"); + foreach (var dll in DLLs) + { + // allows specifying a folder that contains analyzers as well as non-analyzer DLLs without throwing + var newAnalyzers = LoadAnalyzersFromAssembly(dll, false); + if (newAnalyzers.Count() > 0) + { + engine.AddAnalyzers(newAnalyzers); + } + } + } + } + } // Analyzers will hydrate rule enabled/disabled settings // directly from the options referenced by file path @@ -145,15 +202,34 @@ private static async Task RunFormatAsync(FormatOptions options, Cancellatio } } - foreach (var item in options.FormatTargets) + foreach (var item in options.Targets) { - await RunFormatItemAsync(engine, item, options.Language, options.UseAnalyzers, cancellationToken); + // target was a text file with a list of project files to run against + if (StringComparer.OrdinalIgnoreCase.Equals(Path.GetExtension(item), ".txt")) + { + var targets = File.ReadAllLines(item); + foreach (var target in targets) + { + try + { + await RunItemAsync(engine, target, options.Language, options.UseAnalyzers, cancellationToken); + } + catch (Exception e) + { + Console.WriteLine("Exception: {0} with project {1}", e.Message, target); + } + } + } + else + { + await RunItemAsync(engine, item, options.Language, options.UseAnalyzers, cancellationToken); + } } return SUCCEEDED; } - private static async Task RunFormatItemAsync( + private static async Task RunItemAsync( IFormattingEngine engine, string item, string language, @@ -162,32 +238,40 @@ private static async Task RunFormatItemAsync( { Console.WriteLine(Path.GetFileName(item)); string extension = Path.GetExtension(item); - if (StringComparer.OrdinalIgnoreCase.Equals(extension, ".rsp")) + try { - using (var workspace = ResponseFileWorkspace.Create()) + if (StringComparer.OrdinalIgnoreCase.Equals(extension, ".rsp")) { - Project project = workspace.OpenCommandLineProject(item, language); - await engine.FormatProjectAsync(project, useAnalyzers, cancellationToken); + using (var workspace = ResponseFileWorkspace.Create()) + { + Project project = workspace.OpenCommandLineProject(item, language); + await engine.FormatProjectAsync(project, useAnalyzers, cancellationToken); + } } - } - else if (StringComparer.OrdinalIgnoreCase.Equals(extension, ".sln")) - { - using (var workspace = MSBuildWorkspace.Create()) + else if (StringComparer.OrdinalIgnoreCase.Equals(extension, ".sln")) { - workspace.LoadMetadataForReferencedProjects = true; - var solution = await workspace.OpenSolutionAsync(item, cancellationToken); - await engine.FormatSolutionAsync(solution, useAnalyzers, cancellationToken); + using (var workspace = MSBuildWorkspace.Create()) + { + workspace.LoadMetadataForReferencedProjects = true; + var solution = await workspace.OpenSolutionAsync(item, cancellationToken); + await engine.FormatSolutionAsync(solution, useAnalyzers, cancellationToken); + } } - } - else - { - using (var workspace = MSBuildWorkspace.Create()) + else { - workspace.LoadMetadataForReferencedProjects = true; - var project = await workspace.OpenProjectAsync(item, cancellationToken); - await engine.FormatProjectAsync(project, useAnalyzers, cancellationToken); + using (var workspace = MSBuildWorkspace.Create()) + { + workspace.LoadMetadataForReferencedProjects = true; + var project = await workspace.OpenProjectAsync(item, cancellationToken); + await engine.FormatProjectAsync(project, useAnalyzers, cancellationToken); + } } } + catch (Microsoft.Build.Exceptions.InvalidProjectFileException) + { + // Can occur if for example a Mono based project with unknown targets files is supplied + Console.WriteLine("Invalid project file in target {0}", item); + } } private static bool SetRuleMap(IFormattingEngine engine, ImmutableDictionary ruleMap) diff --git a/src/CodeFormatter/packages.config b/src/CodeFormatter/packages.config index ebb7fde4..8a79098e 100644 --- a/src/CodeFormatter/packages.config +++ b/src/CodeFormatter/packages.config @@ -1,14 +1,14 @@  - + - - - - - - + + + + + + @@ -18,7 +18,7 @@ - + diff --git a/src/DeadRegions/App.config b/src/DeadRegions/App.config index b2b36510..a505237b 100644 --- a/src/DeadRegions/App.config +++ b/src/DeadRegions/App.config @@ -15,7 +15,7 @@ - + diff --git a/src/DeadRegions/DeadRegions.csproj b/src/DeadRegions/DeadRegions.csproj index 743ce86f..13dc3a12 100644 --- a/src/DeadRegions/DeadRegions.csproj +++ b/src/DeadRegions/DeadRegions.csproj @@ -12,32 +12,32 @@ - - ..\packages\Microsoft.CodeAnalysis.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.dll + + ..\packages\Microsoft.CodeAnalysis.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True @@ -67,8 +67,8 @@ - - ..\packages\System.Reflection.Metadata.1.1.0\lib\dotnet5.2\System.Reflection.Metadata.dll + + ..\packages\System.Reflection.Metadata.1.2.0-rc3-23811\lib\dotnet5.2\System.Reflection.Metadata.dll True diff --git a/src/DeadRegions/packages.config b/src/DeadRegions/packages.config index 6e7bcf9a..fabdbe28 100644 --- a/src/DeadRegions/packages.config +++ b/src/DeadRegions/packages.config @@ -1,13 +1,13 @@  - + - - - - - - + + + + + + @@ -17,7 +17,7 @@ - + diff --git a/src/Microsoft.DotNet.CodeFormatter.Analyzers.Tests/Microsoft.DotNet.CodeFormatter.Analyzers.Tests.csproj b/src/Microsoft.DotNet.CodeFormatter.Analyzers.Tests/Microsoft.DotNet.CodeFormatter.Analyzers.Tests.csproj index a19d33e8..743d9f7b 100644 --- a/src/Microsoft.DotNet.CodeFormatter.Analyzers.Tests/Microsoft.DotNet.CodeFormatter.Analyzers.Tests.csproj +++ b/src/Microsoft.DotNet.CodeFormatter.Analyzers.Tests/Microsoft.DotNet.CodeFormatter.Analyzers.Tests.csproj @@ -15,32 +15,32 @@ ..\packages\CommandLineParser.2.0.273-beta\lib\net45\CommandLine.dll True - - ..\packages\Microsoft.CodeAnalysis.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.dll + + ..\packages\Microsoft.CodeAnalysis.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True @@ -70,8 +70,8 @@ True - - ..\packages\System.Reflection.Metadata.1.1.0\lib\dotnet5.2\System.Reflection.Metadata.dll + + ..\packages\System.Reflection.Metadata.1.2.0-rc3-23811\lib\dotnet5.2\System.Reflection.Metadata.dll True diff --git a/src/Microsoft.DotNet.CodeFormatter.Analyzers.Tests/app.config b/src/Microsoft.DotNet.CodeFormatter.Analyzers.Tests/app.config index 3fc2bade..2ff0a934 100644 --- a/src/Microsoft.DotNet.CodeFormatter.Analyzers.Tests/app.config +++ b/src/Microsoft.DotNet.CodeFormatter.Analyzers.Tests/app.config @@ -18,6 +18,10 @@ + + + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.CodeFormatter.Analyzers.Tests/packages.config b/src/Microsoft.DotNet.CodeFormatter.Analyzers.Tests/packages.config index ebb7fde4..8a79098e 100644 --- a/src/Microsoft.DotNet.CodeFormatter.Analyzers.Tests/packages.config +++ b/src/Microsoft.DotNet.CodeFormatter.Analyzers.Tests/packages.config @@ -1,14 +1,14 @@  - + - - - - - - + + + + + + @@ -18,7 +18,7 @@ - + diff --git a/src/Microsoft.DotNet.CodeFormatter.Analyzers/Microsoft.DotNet.CodeFormatter.Analyzers.csproj b/src/Microsoft.DotNet.CodeFormatter.Analyzers/Microsoft.DotNet.CodeFormatter.Analyzers.csproj index 9839fd60..c4d5c899 100644 --- a/src/Microsoft.DotNet.CodeFormatter.Analyzers/Microsoft.DotNet.CodeFormatter.Analyzers.csproj +++ b/src/Microsoft.DotNet.CodeFormatter.Analyzers/Microsoft.DotNet.CodeFormatter.Analyzers.csproj @@ -17,32 +17,32 @@ ..\packages\CommandLineParser.2.0.273-beta\lib\net45\CommandLine.dll True - - ..\packages\Microsoft.CodeAnalysis.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.dll + + ..\packages\Microsoft.CodeAnalysis.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True @@ -71,8 +71,8 @@ True - - ..\packages\System.Reflection.Metadata.1.1.0\lib\dotnet5.2\System.Reflection.Metadata.dll + + ..\packages\System.Reflection.Metadata.1.2.0-rc3-23811\lib\dotnet5.2\System.Reflection.Metadata.dll True diff --git a/src/Microsoft.DotNet.CodeFormatter.Analyzers/OptionsHelper.cs b/src/Microsoft.DotNet.CodeFormatter.Analyzers/OptionsHelper.cs index c95ce76a..9065c1ef 100644 --- a/src/Microsoft.DotNet.CodeFormatter.Analyzers/OptionsHelper.cs +++ b/src/Microsoft.DotNet.CodeFormatter.Analyzers/OptionsHelper.cs @@ -101,6 +101,7 @@ public static PerLanguageOption BuildDefaultEnabledProperty(string analyze return new PerLanguageOption(analyzerName, "Enabled", defaultValue: true); } + // TODO: fix hardcoded list internal static IEnumerable AllAnalyzerNames = new string[] { ExplicitThisAnalyzer.AnalyzerName, OptimizeNamespaceImportsAnalyzer.AnalyzerName, diff --git a/src/Microsoft.DotNet.CodeFormatter.Analyzers/app.config b/src/Microsoft.DotNet.CodeFormatter.Analyzers/app.config index 3fc2bade..2ff0a934 100644 --- a/src/Microsoft.DotNet.CodeFormatter.Analyzers/app.config +++ b/src/Microsoft.DotNet.CodeFormatter.Analyzers/app.config @@ -18,6 +18,10 @@ + + + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.CodeFormatter.Analyzers/packages.config b/src/Microsoft.DotNet.CodeFormatter.Analyzers/packages.config index ebb7fde4..8a79098e 100644 --- a/src/Microsoft.DotNet.CodeFormatter.Analyzers/packages.config +++ b/src/Microsoft.DotNet.CodeFormatter.Analyzers/packages.config @@ -1,14 +1,14 @@  - + - - - - - - + + + + + + @@ -18,7 +18,7 @@ - + diff --git a/src/Microsoft.DotNet.CodeFormatting.Tests/FormatOptionsParsingTests.cs b/src/Microsoft.DotNet.CodeFormatting.Tests/FormatOptionsParsingTests.cs index ea4ca45e..1654067b 100644 --- a/src/Microsoft.DotNet.CodeFormatting.Tests/FormatOptionsParsingTests.cs +++ b/src/Microsoft.DotNet.CodeFormatting.Tests/FormatOptionsParsingTests.cs @@ -53,7 +53,7 @@ public void AllRulesEnabled() Assert.Equal(0, result); Assert.NotNull(options); Assert.Equal(12, options.RuleMap.Count); - Assert.Equal(new[] { "test.csproj" }, options.FormatTargets); + Assert.Equal(new[] { "test.csproj" }, options.Targets); foreach (bool enabledSetting in options.RuleMap.Values) { @@ -72,7 +72,7 @@ public void AllRulesDisabled() Assert.Equal(0, result); Assert.NotNull(options); Assert.Equal(12, options.RuleMap.Count); - Assert.Equal(new[] { "test.csproj" }, options.FormatTargets); + Assert.Equal(new[] { "test.csproj" }, options.Targets); foreach(bool enabledSetting in options.RuleMap.Values) { @@ -102,9 +102,9 @@ public void MultipleTargets() Assert.Equal(0, result); Assert.NotNull(options); - Assert.Equal(2, options.FormatTargets.Count()); - Assert.True(options.FormatTargets.Contains("projectOne.csproj")); - Assert.True(options.FormatTargets.Contains("projectTwo.csproj")); + Assert.Equal(2, options.Targets.Count()); + Assert.True(options.Targets.Contains("projectOne.csproj")); + Assert.True(options.Targets.Contains("projectTwo.csproj")); } [Fact] diff --git a/src/Microsoft.DotNet.CodeFormatting.Tests/FormattingEngineCreationTests.cs b/src/Microsoft.DotNet.CodeFormatting.Tests/FormattingEngineCreationTests.cs new file mode 100644 index 00000000..6ceb3bce --- /dev/null +++ b/src/Microsoft.DotNet.CodeFormatting.Tests/FormattingEngineCreationTests.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +using CodeFormatter; +using Microsoft.DotNet.CodeFormatter.Analyzers; +using Xunit; + +namespace Microsoft.DotNet.CodeFormatting.Tests +{ + public class FormattingEngineCreationTests + { + + private static Assembly[] DefaultCompositionAssemblies = + new Assembly[] { + typeof(FormattingEngine).Assembly, + typeof(OptimizeNamespaceImportsAnalyzer).Assembly + }; + // TODO: fix hardcoded path + private static string TestDLLDir = @"E:\src\codeformatter\src\Microsoft.DotNet.CodeFormatting.Tests\TestAnalyzers\"; + private static Assembly RoslynV100Analyzer = Assembly.LoadFile(TestDLLDir + "RoslynV100Analyzer.dll"); + private static Assembly RoslynV110Analyzer = Assembly.LoadFile(TestDLLDir + "RoslynV110Analyzer.dll"); + private static Assembly RoslynV111Analyzer = Assembly.LoadFile(TestDLLDir + "RoslynV111Analyzer.dll"); + private static Assembly RoslynV120Beta1Analyzer = Assembly.LoadFile(TestDLLDir + "RoslynV120Beta1Analyzer.dll"); + + [Fact] + public void AnalyzersBuiltAgainstRoslynV100() + { + IEnumerable roslynV1AnalyzerDLL = new Assembly[] { RoslynV100Analyzer }; + Assert.DoesNotThrow(() => { + var assemblies = DefaultCompositionAssemblies.Concat(roslynV1AnalyzerDLL); + }); + } + + [Fact] + public void AnalyzersBuiltAgainstRoslynV110() + { + IEnumerable roslynV110AnalyzerDLL = new Assembly[] { RoslynV110Analyzer }; + Assert.DoesNotThrow(() => { + var assemblies = DefaultCompositionAssemblies.Concat(roslynV110AnalyzerDLL); + }); + } + + [Fact] + public void AnalyzersBuiltAgainstRoslynV111() + { + IEnumerable roslynV111AnalyzerDLL = new Assembly[] { RoslynV111Analyzer }; + Assert.DoesNotThrow(() => { + var assemblies = DefaultCompositionAssemblies.Concat(roslynV111AnalyzerDLL); + }); + } + + [Fact] + public void AnalyzersBuiltAgainstRoslynV120Beta1() + { + IEnumerable roslynV120Beta1AnalyzerDLL = new Assembly[] { RoslynV120Beta1Analyzer }; + Assert.DoesNotThrow(() => { + var assemblies = DefaultCompositionAssemblies.Concat(roslynV120Beta1AnalyzerDLL); + }); + } + } +} diff --git a/src/Microsoft.DotNet.CodeFormatting.Tests/Microsoft.DotNet.CodeFormatting.Tests.csproj b/src/Microsoft.DotNet.CodeFormatting.Tests/Microsoft.DotNet.CodeFormatting.Tests.csproj index ee57404d..c03afd83 100644 --- a/src/Microsoft.DotNet.CodeFormatting.Tests/Microsoft.DotNet.CodeFormatting.Tests.csproj +++ b/src/Microsoft.DotNet.CodeFormatting.Tests/Microsoft.DotNet.CodeFormatting.Tests.csproj @@ -18,32 +18,32 @@ ..\packages\CommandLineParser.2.0.273-beta\lib\net45\CommandLine.dll True - - ..\packages\Microsoft.CodeAnalysis.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.dll + + ..\packages\Microsoft.CodeAnalysis.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True @@ -73,8 +73,8 @@ True - - ..\packages\System.Reflection.Metadata.1.1.0\lib\dotnet5.2\System.Reflection.Metadata.dll + + ..\packages\System.Reflection.Metadata.1.2.0-rc3-23811\lib\dotnet5.2\System.Reflection.Metadata.dll True @@ -90,6 +90,7 @@ + @@ -144,6 +145,12 @@ + + + + + + diff --git a/src/Microsoft.DotNet.CodeFormatting.Tests/TestAnalyzers/RoslynV100Analyzer.dll b/src/Microsoft.DotNet.CodeFormatting.Tests/TestAnalyzers/RoslynV100Analyzer.dll new file mode 100644 index 00000000..37af5161 Binary files /dev/null and b/src/Microsoft.DotNet.CodeFormatting.Tests/TestAnalyzers/RoslynV100Analyzer.dll differ diff --git a/src/Microsoft.DotNet.CodeFormatting.Tests/TestAnalyzers/RoslynV110Analyzer.dll b/src/Microsoft.DotNet.CodeFormatting.Tests/TestAnalyzers/RoslynV110Analyzer.dll new file mode 100644 index 00000000..0fddb524 Binary files /dev/null and b/src/Microsoft.DotNet.CodeFormatting.Tests/TestAnalyzers/RoslynV110Analyzer.dll differ diff --git a/src/Microsoft.DotNet.CodeFormatting.Tests/TestAnalyzers/RoslynV111Analyzer.dll b/src/Microsoft.DotNet.CodeFormatting.Tests/TestAnalyzers/RoslynV111Analyzer.dll new file mode 100644 index 00000000..ac7b0d4b Binary files /dev/null and b/src/Microsoft.DotNet.CodeFormatting.Tests/TestAnalyzers/RoslynV111Analyzer.dll differ diff --git a/src/Microsoft.DotNet.CodeFormatting.Tests/TestAnalyzers/RoslynV120Beta1Analyzer.dll b/src/Microsoft.DotNet.CodeFormatting.Tests/TestAnalyzers/RoslynV120Beta1Analyzer.dll new file mode 100644 index 00000000..5dafd163 Binary files /dev/null and b/src/Microsoft.DotNet.CodeFormatting.Tests/TestAnalyzers/RoslynV120Beta1Analyzer.dll differ diff --git a/src/Microsoft.DotNet.CodeFormatting.Tests/app.config b/src/Microsoft.DotNet.CodeFormatting.Tests/app.config index 6eb1ab80..e1697c3f 100644 --- a/src/Microsoft.DotNet.CodeFormatting.Tests/app.config +++ b/src/Microsoft.DotNet.CodeFormatting.Tests/app.config @@ -8,7 +8,7 @@ - + diff --git a/src/Microsoft.DotNet.CodeFormatting.Tests/packages.config b/src/Microsoft.DotNet.CodeFormatting.Tests/packages.config index b367d41f..6ba47189 100644 --- a/src/Microsoft.DotNet.CodeFormatting.Tests/packages.config +++ b/src/Microsoft.DotNet.CodeFormatting.Tests/packages.config @@ -1,14 +1,14 @@  - + - - - - - - + + + + + + @@ -18,7 +18,7 @@ - + diff --git a/src/Microsoft.DotNet.CodeFormatting/FormattingEngine.cs b/src/Microsoft.DotNet.CodeFormatting/FormattingEngine.cs index 55beb840..b731f0bf 100644 --- a/src/Microsoft.DotNet.CodeFormatting/FormattingEngine.cs +++ b/src/Microsoft.DotNet.CodeFormatting/FormattingEngine.cs @@ -67,7 +67,6 @@ private static ConventionBuilder GetConventions() .Export(); conventions.ForTypesDerivedFrom() .Export(); - // New per-analyzer options mechanism, deriving // from VS Workspaces functionality conventions.ForTypesDerivedFrom() diff --git a/src/Microsoft.DotNet.CodeFormatting/FormattingEngineImplementation.cs b/src/Microsoft.DotNet.CodeFormatting/FormattingEngineImplementation.cs index 19a3593a..2b91e310 100644 --- a/src/Microsoft.DotNet.CodeFormatting/FormattingEngineImplementation.cs +++ b/src/Microsoft.DotNet.CodeFormatting/FormattingEngineImplementation.cs @@ -7,7 +7,9 @@ using System.Collections.Immutable; using System.Composition; using System.Diagnostics; +using System.IO; using System.Linq; +using System.Reflection; using System.Threading; using System.Threading.Tasks; @@ -31,7 +33,7 @@ internal sealed partial class FormattingEngineImplementation : IFormattingEngine private readonly FormattingOptions _options; private readonly IEnumerable _fixers; private readonly IEnumerable _filters; - private readonly IEnumerable _analyzers; + private IEnumerable _analyzers; private readonly IEnumerable _optionsProviders; private readonly IEnumerable> _syntaxRules; private readonly IEnumerable> _localSemanticRules; @@ -39,6 +41,9 @@ internal sealed partial class FormattingEngineImplementation : IFormattingEngine private readonly Stopwatch _watch = new Stopwatch(); private readonly Dictionary _ruleEnabledMap = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly ImmutableDictionary _diagnosticIdToFixerMap; + private CompilationWithAnalyzers _compilationWithAnalyzers; + private object _outputLogger; // Microsoft.CodeAnalysis.ErrorLogger + private Assembly _loggerAssembly; public ImmutableArray CopyrightHeader { @@ -70,6 +75,10 @@ public IFormatLogger FormatLogger public string FormattingOptionsFilePath { get; set; } + public bool ApplyFixes { get; set; } + + public string LogOutputPath { get; set; } + public ImmutableArray AllRules { get @@ -88,6 +97,27 @@ public ImmutableArray AllSupportedDiagnostics .OrderBy(a => a.Id) .ToImmutableArray(); + // Use the Roslyn ErrorLogger type to log diagnostics per analyzer to SARIF format + public void LogDiagnostics(string filePath, ImmutableArray diagnostics) + { + if (_loggerAssembly == null) + { + _loggerAssembly = Assembly.Load(typeof(CommandLineParser).Assembly.FullName); + } + + _outputLogger = Activator.CreateInstance( + _loggerAssembly.GetType("Microsoft.CodeAnalysis.ErrorLogger"), + new object[] { new FileStream(filePath, FileMode.Append, FileAccess.Write), "CodeFormatter", "0.1", _loggerAssembly.GetName().Version }); + + var logDiagMethodInfo = _outputLogger.GetType().GetMethod("LogDiagnostic", BindingFlags.NonPublic | BindingFlags.Instance); + foreach (var diagnostic in diagnostics) + { + logDiagMethodInfo.Invoke(_outputLogger, new object[] { diagnostic, System.Globalization.CultureInfo.DefaultThreadCurrentCulture }); + } + + ((IDisposable)_outputLogger).Dispose(); + } + public FormattingEngineImplementation( FormattingOptions options, IEnumerable filters, @@ -211,6 +241,7 @@ public async Task FormatProjectWithAnalyzersAsync(Project project, CancellationT await FormatProjectWithSyntaxAnalyzersAsync(workspace, project.Id, cancellationToken); await FormatProjectWithLocalAnalyzersAsync(workspace, project.Id, cancellationToken); await FormatProjectWithGlobalAnalyzersAsync(workspace, project.Id, cancellationToken); + await FormatProjectWithUnspecifiedAnalyzersAsync(workspace, project.Id, cancellationToken); watch.Stop(); FormatLogger.WriteLine("Total time for formatting {0} - {1}", project.Name, watch.Elapsed); @@ -239,32 +270,67 @@ private async Task FormatProjectWithGlobalAnalyzersAsync(Workspace workspace, Pr } } - private async Task FormatWithAnalyzersCoreAsync(Workspace workspace, ProjectId projectId, IEnumerable analyzers, CancellationToken cancellationToken) + private async Task FormatProjectWithUnspecifiedAnalyzersAsync(Workspace workspace, ProjectId projectId, CancellationToken cancellationToken) { - var project = workspace.CurrentSolution.GetProject(projectId); - var diagnostics = await GetDiagnostics(project, analyzers, cancellationToken).ConfigureAwait(false); - - var batchFixer = WellKnownFixAllProviders.BatchFixer; + var analyzers = _analyzers.Where(a => a.SupportedDiagnostics.All(d => { + return !(d.CustomTags.Contains(RuleType.Syntactic) || d.CustomTags.Contains(RuleType.LocalSemantic) || d.CustomTags.Contains(RuleType.GlobalSemantic)); + })); - var context = new FixAllContext( - project.Documents.First(), // TODO: Shouldn't this be the whole project? - new UberCodeFixer(_diagnosticIdToFixerMap), - FixAllScope.Project, - null, - diagnostics.Select(d => d.Id), - new FormattingEngineDiagnosticProvider(project, diagnostics), - cancellationToken); + // Treat analyzers with unknown rule types as if they were global in case they might conflict with each other + foreach (var analyzer in analyzers) + { + await FormatWithAnalyzersCoreAsync(workspace, projectId, new[] { analyzer }, cancellationToken); + } + } - var fix = await batchFixer.GetFixAsync(context).ConfigureAwait(false); - if (fix != null) + private async Task FormatWithAnalyzersCoreAsync(Workspace workspace, ProjectId projectId, IEnumerable analyzers, CancellationToken cancellationToken) + { + if (analyzers != null && analyzers.Count() != 0) { - foreach (var operation in await fix.GetOperationsAsync(cancellationToken).ConfigureAwait(false)) + var project = workspace.CurrentSolution.GetProject(projectId); + var diagnostics = await GetDiagnostics(project, analyzers, cancellationToken).ConfigureAwait(false); + // Ensure at least 1 analyzer supporting the current project's language ran + if (_compilationWithAnalyzers != null) { - operation.Apply(workspace, cancellationToken); + var extension = StringComparer.OrdinalIgnoreCase.Equals(project.Language, "C#") ? ".csproj" : ".vbproj"; + var resultFile = project.FilePath.Substring(project.FilePath.LastIndexOf(Path.DirectorySeparatorChar)).Replace(extension, "_CodeFormatterResults.txt"); + + foreach (var analyzer in analyzers) + { + var diags = await _compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(ImmutableArray.Create(analyzer), cancellationToken); + if (Verbose || LogOutputPath != null) + { + var analyzerTelemetryInfo = await _compilationWithAnalyzers.GetAnalyzerTelemetryInfoAsync(analyzer, cancellationToken); + var resultPath = Path.ChangeExtension(LogOutputPath + resultFile, "json"); + LogDiagnostics(resultPath, diags); + } + } + } + + if (ApplyFixes) + { + var batchFixer = WellKnownFixAllProviders.BatchFixer; + var context = new FixAllContext( + project.Documents.First(), // TODO: Shouldn't this be the whole project? + new UberCodeFixer(_diagnosticIdToFixerMap), + FixAllScope.Project, + null, + diagnostics.Select(d => d.Id), + new FormattingEngineDiagnosticProvider(project, diagnostics), + cancellationToken); + + var fix = await batchFixer.GetFixAsync(context).ConfigureAwait(false); + if (fix != null) + { + foreach (var operation in await fix.GetOperationsAsync(cancellationToken).ConfigureAwait(false)) + { + operation.Apply(workspace, cancellationToken); + } + } } } } - + public void ToggleRuleEnabled(IRuleMetadata ruleMetaData, bool enabled) { _ruleEnabledMap[ruleMetaData.Name] = enabled; @@ -389,10 +455,12 @@ private async Task> GetDiagnostics(Project project, I if (analyzersToRun.Any()) { var compilationWithAnalyzers = compilation.WithAnalyzers(analyzersToRun.ToImmutableArray(), analyzerOptions); + _compilationWithAnalyzers = compilationWithAnalyzers; return await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().ConfigureAwait(false); } else { + _compilationWithAnalyzers = null; return ImmutableArray.Empty; } } @@ -570,5 +638,33 @@ private async Task RunGlobalSemanticPass(Solution solution, IReadOnlyL return solution; } + + public void AddAnalyzers(ImmutableArray analyzers) + { + var toAdd = new List(); + foreach (var analyzer in analyzers) + { + IEqualityComparer comparer = new AnalyzerComparer(); + if (!_analyzers.Contains(analyzer, comparer)) + { + toAdd.Add(analyzer); + } + } + _analyzers = _analyzers.Concat(toAdd.ToArray()); + } + } + + // Simple comparer to ensure we don't add the same analyzer twice given large lists of analyzer assemblies + internal class AnalyzerComparer : IEqualityComparer + { + public bool Equals(DiagnosticAnalyzer x, DiagnosticAnalyzer y) + { + return x.ToString() == y.ToString(); + } + + public int GetHashCode(DiagnosticAnalyzer obj) + { + return obj.GetHashCode(); + } } -} +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.CodeFormatting/IFormattingEngine.cs b/src/Microsoft.DotNet.CodeFormatting/IFormattingEngine.cs index 183a5604..4fbc9651 100644 --- a/src/Microsoft.DotNet.CodeFormatting/IFormattingEngine.cs +++ b/src/Microsoft.DotNet.CodeFormatting/IFormattingEngine.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; namespace Microsoft.DotNet.CodeFormatting { @@ -20,8 +21,12 @@ public interface IFormattingEngine bool AllowTables { get; set; } bool Verbose { get; set; } string FormattingOptionsFilePath { get; set; } + bool ApplyFixes { get; set; } + string LogOutputPath { get; set; } + void ToggleRuleEnabled(IRuleMetadata ruleMetaData, bool enabled); Task FormatSolutionAsync(Solution solution, bool useAnalyzers, CancellationToken cancellationToken); Task FormatProjectAsync(Project project, bool useAnalyzers, CancellationToken cancellationToken); + void AddAnalyzers(ImmutableArray immutableArray); } } diff --git a/src/Microsoft.DotNet.CodeFormatting/Microsoft.DotNet.CodeFormatting.csproj b/src/Microsoft.DotNet.CodeFormatting/Microsoft.DotNet.CodeFormatting.csproj index 5870681f..19378cf8 100644 --- a/src/Microsoft.DotNet.CodeFormatting/Microsoft.DotNet.CodeFormatting.csproj +++ b/src/Microsoft.DotNet.CodeFormatting/Microsoft.DotNet.CodeFormatting.csproj @@ -9,32 +9,32 @@ Microsoft.DotNet.CodeFormatting - - ..\packages\Microsoft.CodeAnalysis.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.dll + + ..\packages\Microsoft.CodeAnalysis.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True @@ -63,8 +63,8 @@ True - - ..\packages\System.Reflection.Metadata.1.1.0\lib\dotnet5.2\System.Reflection.Metadata.dll + + ..\packages\System.Reflection.Metadata.1.2.0-rc3-23811\lib\dotnet5.2\System.Reflection.Metadata.dll True diff --git a/src/Microsoft.DotNet.CodeFormatting/app.config b/src/Microsoft.DotNet.CodeFormatting/app.config index 6eb1ab80..e1697c3f 100644 --- a/src/Microsoft.DotNet.CodeFormatting/app.config +++ b/src/Microsoft.DotNet.CodeFormatting/app.config @@ -8,7 +8,7 @@ - + diff --git a/src/Microsoft.DotNet.CodeFormatting/packages.config b/src/Microsoft.DotNet.CodeFormatting/packages.config index 6e7bcf9a..fabdbe28 100644 --- a/src/Microsoft.DotNet.CodeFormatting/packages.config +++ b/src/Microsoft.DotNet.CodeFormatting/packages.config @@ -1,13 +1,13 @@  - + - - - - - - + + + + + + @@ -17,7 +17,7 @@ - + diff --git a/src/Microsoft.DotNet.DeadRegionAnalysis.Tests/Microsoft.DotNet.DeadRegionAnalysis.Tests.csproj b/src/Microsoft.DotNet.DeadRegionAnalysis.Tests/Microsoft.DotNet.DeadRegionAnalysis.Tests.csproj index 683a1f4f..600c001f 100644 --- a/src/Microsoft.DotNet.DeadRegionAnalysis.Tests/Microsoft.DotNet.DeadRegionAnalysis.Tests.csproj +++ b/src/Microsoft.DotNet.DeadRegionAnalysis.Tests/Microsoft.DotNet.DeadRegionAnalysis.Tests.csproj @@ -13,32 +13,32 @@ - - ..\packages\Microsoft.CodeAnalysis.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.dll + + ..\packages\Microsoft.CodeAnalysis.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True @@ -68,8 +68,8 @@ - - ..\packages\System.Reflection.Metadata.1.1.0\lib\dotnet5.2\System.Reflection.Metadata.dll + + ..\packages\System.Reflection.Metadata.1.2.0-rc3-23811\lib\dotnet5.2\System.Reflection.Metadata.dll True diff --git a/src/Microsoft.DotNet.DeadRegionAnalysis.Tests/app.config b/src/Microsoft.DotNet.DeadRegionAnalysis.Tests/app.config index e3380ab7..a06c9e74 100644 --- a/src/Microsoft.DotNet.DeadRegionAnalysis.Tests/app.config +++ b/src/Microsoft.DotNet.DeadRegionAnalysis.Tests/app.config @@ -8,7 +8,7 @@ - + diff --git a/src/Microsoft.DotNet.DeadRegionAnalysis.Tests/packages.config b/src/Microsoft.DotNet.DeadRegionAnalysis.Tests/packages.config index 1dccdf88..201ccef8 100644 --- a/src/Microsoft.DotNet.DeadRegionAnalysis.Tests/packages.config +++ b/src/Microsoft.DotNet.DeadRegionAnalysis.Tests/packages.config @@ -1,13 +1,13 @@  - + - - - - - - + + + + + + @@ -17,7 +17,7 @@ - + diff --git a/src/Microsoft.DotNet.DeadRegionAnalysis/Microsoft.DotNet.DeadRegionAnalysis.csproj b/src/Microsoft.DotNet.DeadRegionAnalysis/Microsoft.DotNet.DeadRegionAnalysis.csproj index 79dc0abb..0f55e28c 100644 --- a/src/Microsoft.DotNet.DeadRegionAnalysis/Microsoft.DotNet.DeadRegionAnalysis.csproj +++ b/src/Microsoft.DotNet.DeadRegionAnalysis/Microsoft.DotNet.DeadRegionAnalysis.csproj @@ -12,32 +12,32 @@ - - ..\packages\Microsoft.CodeAnalysis.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.dll + + ..\packages\Microsoft.CodeAnalysis.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True @@ -67,8 +67,8 @@ - - ..\packages\System.Reflection.Metadata.1.1.0\lib\dotnet5.2\System.Reflection.Metadata.dll + + ..\packages\System.Reflection.Metadata.1.2.0-rc3-23811\lib\dotnet5.2\System.Reflection.Metadata.dll True diff --git a/src/Microsoft.DotNet.DeadRegionAnalysis/app.config b/src/Microsoft.DotNet.DeadRegionAnalysis/app.config index 3fc2bade..2ff0a934 100644 --- a/src/Microsoft.DotNet.DeadRegionAnalysis/app.config +++ b/src/Microsoft.DotNet.DeadRegionAnalysis/app.config @@ -18,6 +18,10 @@ + + + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.DeadRegionAnalysis/packages.config b/src/Microsoft.DotNet.DeadRegionAnalysis/packages.config index 6e7bcf9a..fabdbe28 100644 --- a/src/Microsoft.DotNet.DeadRegionAnalysis/packages.config +++ b/src/Microsoft.DotNet.DeadRegionAnalysis/packages.config @@ -1,13 +1,13 @@  - + - - - - - - + + + + + + @@ -17,7 +17,7 @@ - + diff --git a/src/XUnitConverter.Tests/XUnitConverter.Tests.csproj b/src/XUnitConverter.Tests/XUnitConverter.Tests.csproj index bfe30ce9..edbdeff3 100644 --- a/src/XUnitConverter.Tests/XUnitConverter.Tests.csproj +++ b/src/XUnitConverter.Tests/XUnitConverter.Tests.csproj @@ -14,32 +14,32 @@ - - ..\packages\Microsoft.CodeAnalysis.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.dll + + ..\packages\Microsoft.CodeAnalysis.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True @@ -69,8 +69,8 @@ True - - ..\packages\System.Reflection.Metadata.1.1.0\lib\dotnet5.2\System.Reflection.Metadata.dll + + ..\packages\System.Reflection.Metadata.1.2.0-rc3-23811\lib\dotnet5.2\System.Reflection.Metadata.dll True diff --git a/src/XUnitConverter.Tests/app.config b/src/XUnitConverter.Tests/app.config index e3380ab7..a06c9e74 100644 --- a/src/XUnitConverter.Tests/app.config +++ b/src/XUnitConverter.Tests/app.config @@ -8,7 +8,7 @@ - + diff --git a/src/XUnitConverter.Tests/packages.config b/src/XUnitConverter.Tests/packages.config index 1dccdf88..201ccef8 100644 --- a/src/XUnitConverter.Tests/packages.config +++ b/src/XUnitConverter.Tests/packages.config @@ -1,13 +1,13 @@  - + - - - - - - + + + + + + @@ -17,7 +17,7 @@ - + diff --git a/src/XUnitConverter/App.config b/src/XUnitConverter/App.config index b8a5afac..0166ec16 100644 --- a/src/XUnitConverter/App.config +++ b/src/XUnitConverter/App.config @@ -15,7 +15,7 @@ - + diff --git a/src/XUnitConverter/XUnitConverter.csproj b/src/XUnitConverter/XUnitConverter.csproj index 34e678e6..662bf083 100644 --- a/src/XUnitConverter/XUnitConverter.csproj +++ b/src/XUnitConverter/XUnitConverter.csproj @@ -12,32 +12,32 @@ - - ..\packages\Microsoft.CodeAnalysis.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.dll + + ..\packages\Microsoft.CodeAnalysis.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.dll True - - ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.dll True - - ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.VisualBasic.Workspaces.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll True - - ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll + + ..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.2.0-beta1-20160226-01\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll True @@ -66,8 +66,8 @@ True - - ..\packages\System.Reflection.Metadata.1.1.0\lib\dotnet5.2\System.Reflection.Metadata.dll + + ..\packages\System.Reflection.Metadata.1.2.0-rc3-23811\lib\dotnet5.2\System.Reflection.Metadata.dll True diff --git a/src/XUnitConverter/packages.config b/src/XUnitConverter/packages.config index 6e7bcf9a..fabdbe28 100644 --- a/src/XUnitConverter/packages.config +++ b/src/XUnitConverter/packages.config @@ -1,13 +1,13 @@  - + - - - - - - + + + + + + @@ -17,7 +17,7 @@ - +