Skip to content

Commit

Permalink
Add option for whitespace formatting (#774)
Browse files Browse the repository at this point in the history
* Add option for whitespace formatting

* Fix formatting

* Fix validation CI

* Add fix prefix to options
  • Loading branch information
JoeRobich committed Sep 9, 2020
1 parent fd64735 commit 6e49a72
Show file tree
Hide file tree
Showing 43 changed files with 227 additions and 94 deletions.
29 changes: 16 additions & 13 deletions README.md
Expand Up @@ -72,8 +72,9 @@ Arguments:

Options:
--folder, -f Whether to treat the `<workspace>` argument as a simple folder of files.
--fix-style <severity> Run code style analyzers and apply fixes.
--fix-analyzers <severity> Run 3rd party analyzers and apply fixes.
--fix-whitespace, -w Run whitespace formatting. Run by default when not applying fixes.
--fix-style, -s <severity> Run code style analyzers and apply fixes.
--fix-analyzers, -a <severity> Run 3rd party analyzers and apply fixes.
--include <include> A list of relative file or folder paths to include in formatting. All files are formatted if empty.
--exclude <exclude> A list of relative file or folder paths to exclude from formatting.
--check Formats files without saving changes to disk. Terminates with a non-zero exit code if any files were formatted.
Expand All @@ -84,17 +85,19 @@ Options:

Add `format` after `dotnet` and before the command arguments that you want to run:

| Examples | Description |
| ---------------------------------------------------------- |---------------------------------------------------------------------------------------------- |
| dotnet **format** | Formats the project or solution in the current directory. |
| dotnet **format** &lt;workspace&gt; | Formats a specific project or solution. |
| dotnet **format** &lt;workspace&gt; -f | Formats a particular folder and subfolders. |
| dotnet **format** &lt;workspace&gt; --fix-style warn | Formats and fixes codestyle analyzer warnings. |
| dotnet **format** &lt;workspace&gt; --fix-analyzers | Formats and fixes 3rd party analyzer errors. |
| dotnet **format** -v diag | Formats with very verbose logging. |
| dotnet **format** --include Programs.cs Utility\Logging.cs | Formats the files Program.cs and Utility\Logging.cs |
| dotnet **format** --check | Formats but does not save. Returns a non-zero exit code if any files would have been changed. |
| dotnet **format** --report &lt;report-path&gt; | Formats and saves a json report file to the given directory. |
| Examples | Description |
| ---------------------------------------------------------------- |---------------------------------------------------------------------------------------------- |
| dotnet **format** | Formats the project or solution in the current directory. |
| dotnet **format** &lt;workspace&gt; | Formats a specific project or solution. |
| dotnet **format** &lt;workspace&gt; -f | Formats a particular folder and subfolders. |
| dotnet **format** &lt;workspace&gt; --fix-style warn | Fixes only codestyle analyzer warnings. |
| dotnet **format** &lt;workspace&gt; --fix-whitespace --fix-style | Formats and fixes codestyle analyzer errors. |
| dotnet **format** &lt;workspace&gt; --fix-analyzers | Fixes only 3rd party analyzer errors. |
| dotnet **format** &lt;workspace&gt; -wsa | Formats, fixes codestyle errors, and fixes 3rd party analyzer errors. |
| dotnet **format** -v diag | Formats with very verbose logging. |
| dotnet **format** --include Programs.cs Utility\Logging.cs | Formats the files Program.cs and Utility\Logging.cs |
| dotnet **format** --check | Formats but does not save. Returns a non-zero exit code if any files would have been changed. |
| dotnet **format** --report &lt;report-path&gt; | Formats and saves a json report file to the given directory. |

### How To Uninstall

Expand Down
18 changes: 17 additions & 1 deletion docs/README.md
Expand Up @@ -32,6 +32,22 @@ Format the code files from the `./src` folder.
dotnet-format ./src --folder
```

### Whitespace formatting

Whitespace formatting includes the core .editorconfig settings along with the placement of spaces and newlines. The whitespace formatter is run by default when not running analysis. When you want to run analysis and fix formatting issues you must specify both.

Whitespace formatting run by default.

```console
dotnet-format ./format.sln
```

Running the whitespace formatter along with code-style analysis.

```console
dotnet-format ./format.sln --fix-whitespace --fix-style
```

### Running analysis

#### CodeStyle analysis
Expand All @@ -42,7 +58,7 @@ Running codestyle analysis requires the use of a MSBuild solution or project fil

*Example:*

Run analysis against the format solution and fix errors.
Run code-style analysis against the format solution and fix errors.

```console
dotnet-format ./format.sln --fix-style
Expand Down
2 changes: 1 addition & 1 deletion eng/format-verifier.ps1
Expand Up @@ -62,7 +62,7 @@ try {

if ($stage -eq "format-workspace") {
Write-Output "$(Get-Date) - $solutionFile - Formatting Workspace"
$output = dotnet.exe run -p "$currentLocation\src\dotnet-format.csproj" -c Release -- $solution --fix-style --fix-analyzers -v diag --check | Out-String
$output = dotnet.exe run -p "$currentLocation\src\dotnet-format.csproj" -c Release -- $solution -wsa -v diag --check | Out-String
Write-Output $output.TrimEnd()

# Ignore CheckFailedExitCode since we don't expect these repos to be properly formatted.
Expand Down
9 changes: 3 additions & 6 deletions perf/FormattedFiles.cs
Expand Up @@ -33,9 +33,8 @@ public void FilesFormattedFolder()
workspacePath,
workspaceType,
LogLevel.Error,
fixCodeStyle: false,
fixCategory: FixCategory.Whitespace,
codeStyleSeverity: DiagnosticSeverity.Error,
fixAnalyzers: false,
analyzerSeverity: DiagnosticSeverity.Error,
saveFormattedFiles: false,
changesAreErrors: false,
Expand All @@ -53,9 +52,8 @@ public void FilesFormattedProject()
workspacePath,
workspaceType,
LogLevel.Error,
fixCodeStyle: false,
fixCategory: FixCategory.Whitespace,
codeStyleSeverity: DiagnosticSeverity.Error,
fixAnalyzers: false,
analyzerSeverity: DiagnosticSeverity.Error,
saveFormattedFiles: false,
changesAreErrors: false,
Expand All @@ -73,9 +71,8 @@ public void FilesFormattedSolution()
workspacePath,
workspaceType,
LogLevel.Error,
fixCodeStyle: false,
fixCategory: FixCategory.Whitespace,
codeStyleSeverity: DiagnosticSeverity.Error,
fixAnalyzers: false,
analyzerSeverity: DiagnosticSeverity.Error,
saveFormattedFiles: false,
changesAreErrors: false,
Expand Down
9 changes: 3 additions & 6 deletions perf/NoFilesFormatted.cs
Expand Up @@ -33,9 +33,8 @@ public void NoFilesFormattedFolder()
workspacePath,
workspaceType,
LogLevel.Error,
fixCodeStyle: false,
fixCategory: FixCategory.Whitespace,
codeStyleSeverity: DiagnosticSeverity.Error,
fixAnalyzers: false,
analyzerSeverity: DiagnosticSeverity.Error,
saveFormattedFiles: false,
changesAreErrors: false,
Expand All @@ -53,9 +52,8 @@ public void NoFilesFormattedProject()
workspacePath,
workspaceType,
LogLevel.Error,
fixCodeStyle: false,
fixCategory: FixCategory.Whitespace,
codeStyleSeverity: DiagnosticSeverity.Error,
fixAnalyzers: false,
analyzerSeverity: DiagnosticSeverity.Error,
saveFormattedFiles: false,
changesAreErrors: false,
Expand All @@ -73,9 +71,8 @@ public void NoFilesFormattedSolution()
workspacePath,
workspaceType,
LogLevel.Error,
fixCodeStyle: false,
fixCategory: FixCategory.Whitespace,
codeStyleSeverity: DiagnosticSeverity.Error,
fixAnalyzers: false,
analyzerSeverity: DiagnosticSeverity.Error,
saveFormattedFiles: false,
changesAreErrors: false,
Expand Down
6 changes: 2 additions & 4 deletions perf/RealWorldSolution.cs
Expand Up @@ -35,9 +35,8 @@ public void FilesFormattedSolution()
workspacePath,
workspaceType,
LogLevel.Error,
fixCodeStyle: false,
fixCategory: FixCategory.Whitespace,
codeStyleSeverity: DiagnosticSeverity.Error,
fixAnalyzers: false,
analyzerSeverity: DiagnosticSeverity.Error,
saveFormattedFiles: false,
changesAreErrors: false,
Expand All @@ -55,9 +54,8 @@ public void FilesFormattedFolder()
workspacePath,
workspaceType,
LogLevel.Error,
fixCodeStyle: false,
fixCategory: FixCategory.Whitespace,
codeStyleSeverity: DiagnosticSeverity.Error,
fixAnalyzers: false,
analyzerSeverity: DiagnosticSeverity.Error,
saveFormattedFiles: false,
changesAreErrors: false,
Expand Down
4 changes: 4 additions & 0 deletions src/Analyzers/AnalyzerFormatter.cs
Expand Up @@ -21,13 +21,17 @@ internal class AnalyzerFormatter : ICodeFormatter
private readonly IAnalyzerRunner _runner;
private readonly ICodeFixApplier _applier;

public FixCategory Category { get; }

public AnalyzerFormatter(
string name,
FixCategory category,
IAnalyzerInformationProvider informationProvider,
IAnalyzerRunner runner,
ICodeFixApplier applier)
{
_name = name;
Category = category;
_informationProvider = informationProvider;
_runner = runner;
_applier = applier;
Expand Down
5 changes: 0 additions & 5 deletions src/Analyzers/AnalyzerReferenceInformationProvider.cs
Expand Up @@ -17,11 +17,6 @@ internal class AnalyzerReferenceInformationProvider : IAnalyzerInformationProvid
FormatOptions formatOptions,
ILogger logger)
{
if (!formatOptions.FixAnalyzers)
{
return ImmutableDictionary<ProjectId, AnalyzersAndFixers>.Empty;
}

return solution.Projects
.ToImmutableDictionary(project => project.Id, GetAnalyzersAndFixers);
}
Expand Down
7 changes: 1 addition & 6 deletions src/Analyzers/CodeStyleInformationProvider.cs
Expand Up @@ -18,14 +18,9 @@ internal class CodeStyleInformationProvider : IAnalyzerInformationProvider

public ImmutableDictionary<ProjectId, AnalyzersAndFixers> GetAnalyzersAndFixers(
Solution solution,
FormatOptions options,
FormatOptions formatOptions,
ILogger logger)
{
if (!options.FixCodeStyle)
{
return ImmutableDictionary<ProjectId, AnalyzersAndFixers>.Empty;
}

var assemblies = new[]
{
_featuresPath,
Expand Down
10 changes: 8 additions & 2 deletions src/CodeFormatter.cs
Expand Up @@ -25,8 +25,8 @@ internal static class CodeFormatter
new CharsetFormatter(),
new OrganizeImportsFormatter(),
new UnnecessaryImportsFormatter(),
new AnalyzerFormatter(Resources.Code_Style, new CodeStyleInformationProvider(), new AnalyzerRunner(), new SolutionCodeFixApplier()),
new AnalyzerFormatter(Resources.Analyzer_Reference, new AnalyzerReferenceInformationProvider(), new AnalyzerRunner(), new SolutionCodeFixApplier()));
new AnalyzerFormatter(Resources.Code_Style, FixCategory.CodeStyle, new CodeStyleInformationProvider(), new AnalyzerRunner(), new SolutionCodeFixApplier()),
new AnalyzerFormatter(Resources.Analyzer_Reference, FixCategory.Analyzers, new AnalyzerReferenceInformationProvider(), new AnalyzerRunner(), new SolutionCodeFixApplier()));

public static async Task<WorkspaceFormatResult> FormatWorkspaceAsync(
FormatOptions formatOptions,
Expand Down Expand Up @@ -132,6 +132,12 @@ private static Workspace OpenFolderWorkspace(string workspacePath, SourceFileMat

for (var index = 0; index < s_codeFormatters.Length; index++)
{
// Only run the formatter if it belongs to one of the categories being fixed.
if (!formatOptions.FixCategory.HasFlag(s_codeFormatters[index].Category))
{
continue;
}

formattedSolution = await s_codeFormatters[index].FormatAsync(formattedSolution, formattableDocuments, formatOptions, logger, formattedFiles, cancellationToken).ConfigureAwait(false);
}

Expand Down
15 changes: 15 additions & 0 deletions src/FixCategory.cs
@@ -0,0 +1,15 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.

using System;

namespace Microsoft.CodeAnalysis.Tools
{
[Flags]
internal enum FixCategory
{
None = 0,
Whitespace = 1,
CodeStyle = 2,
Analyzers = 4
}
}
5 changes: 3 additions & 2 deletions src/FormatCommand.cs
Expand Up @@ -22,11 +22,12 @@ internal static RootCommand CreateCommandLineOptions()
Description = Resources.A_path_to_a_solution_file_a_project_file_or_a_folder_containing_a_solution_or_project_file_If_a_path_is_not_specified_then_the_current_directory_is_used
}.LegalFilePathsOnly(),
new Option(new[] { "--folder", "-f" }, Resources.Whether_to_treat_the_workspace_argument_as_a_simple_folder_of_files),
new Option(new[] { "--fix-style" }, Resources.Run_code_style_analyzers_and_apply_fixes)
new Option(new[] { "--fix-whitespace", "-w" }, Resources.Run_whitespace_formatting_Run_by_default_when_not_applying_fixes),
new Option(new[] { "--fix-style", "-s" }, Resources.Run_code_style_analyzers_and_apply_fixes)
{
Argument = new Argument<string?>("severity") { Arity = ArgumentArity.ZeroOrOne }.FromAmong(SeverityLevels)
},
new Option(new[] { "--fix-analyzers" }, Resources.Run_3rd_party_analyzers_and_apply_fixes)
new Option(new[] { "--fix-analyzers", "-a" }, Resources.Run_3rd_party_analyzers_and_apply_fixes)
{
Argument = new Argument<string?>("severity") { Arity = ArgumentArity.ZeroOrOne }.FromAmong(SeverityLevels)
},
Expand Down
15 changes: 5 additions & 10 deletions src/FormatOptions.cs
Expand Up @@ -10,9 +10,8 @@ internal class FormatOptions
public string WorkspaceFilePath { get; }
public WorkspaceType WorkspaceType { get; }
public LogLevel LogLevel { get; }
public bool FixCodeStyle { get; }
public FixCategory FixCategory { get; }
public DiagnosticSeverity CodeStyleSeverity { get; }
public bool FixAnalyzers { get; }
public DiagnosticSeverity AnalyzerSeverity { get; }
public bool SaveFormattedFiles { get; }
public bool ChangesAreErrors { get; }
Expand All @@ -24,9 +23,8 @@ internal class FormatOptions
string workspaceFilePath,
WorkspaceType workspaceType,
LogLevel logLevel,
bool fixCodeStyle,
FixCategory fixCategory,
DiagnosticSeverity codeStyleSeverity,
bool fixAnalyzers,
DiagnosticSeverity analyzerSeverity,
bool saveFormattedFiles,
bool changesAreErrors,
Expand All @@ -37,9 +35,8 @@ internal class FormatOptions
WorkspaceFilePath = workspaceFilePath;
WorkspaceType = workspaceType;
LogLevel = logLevel;
FixCodeStyle = fixCodeStyle;
FixCategory = fixCategory;
CodeStyleSeverity = codeStyleSeverity;
FixAnalyzers = fixAnalyzers;
AnalyzerSeverity = analyzerSeverity;
SaveFormattedFiles = saveFormattedFiles;
ChangesAreErrors = changesAreErrors;
Expand All @@ -52,9 +49,8 @@ internal class FormatOptions
out string workspaceFilePath,
out WorkspaceType workspaceType,
out LogLevel logLevel,
out bool fixCodeStyle,
out FixCategory fixCategory,
out DiagnosticSeverity codeStyleSeverity,
out bool fixAnalyzers,
out DiagnosticSeverity analyzerSeverity,
out bool saveFormattedFiles,
out bool changesAreErrors,
Expand All @@ -65,9 +61,8 @@ internal class FormatOptions
workspaceFilePath = WorkspaceFilePath;
workspaceType = WorkspaceType;
logLevel = LogLevel;
fixCodeStyle = FixCodeStyle;
fixCategory = FixCategory;
codeStyleSeverity = CodeStyleSeverity;
fixAnalyzers = FixAnalyzers;
analyzerSeverity = AnalyzerSeverity;
saveFormattedFiles = SaveFormattedFiles;
changesAreErrors = ChangesAreErrors;
Expand Down
2 changes: 2 additions & 0 deletions src/Formatters/CharsetFormatter.cs
Expand Up @@ -20,6 +20,8 @@ internal sealed class CharsetFormatter : DocumentFormatter
private static Encoding Utf8 => new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
private static Encoding Latin1 => Encoding.GetEncoding("iso-8859-1");

public override FixCategory Category => FixCategory.Whitespace;

internal override Task<SourceText> FormatFileAsync(
Document document,
SourceText sourceText,
Expand Down
5 changes: 5 additions & 0 deletions src/Formatters/DocumentFormatter.cs
Expand Up @@ -20,6 +20,11 @@ internal abstract class DocumentFormatter : ICodeFormatter
{
protected abstract string FormatWarningDescription { get; }

/// <summary>
/// Gets the fix category this formatter belongs to.
/// </summary>
public abstract FixCategory Category { get; }

/// <summary>
/// Applies formatting and returns a formatted <see cref="Solution"/>
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Formatters/EndOfLineFormatter.cs
Expand Up @@ -15,6 +15,8 @@ internal sealed class EndOfLineFormatter : DocumentFormatter
{
protected override string FormatWarningDescription => Resources.Fix_end_of_line_marker;

public override FixCategory Category => FixCategory.Whitespace;

internal override Task<SourceText> FormatFileAsync(
Document document,
SourceText sourceText,
Expand Down
2 changes: 2 additions & 0 deletions src/Formatters/FinalNewlineFormatter.cs
Expand Up @@ -14,6 +14,8 @@ internal sealed class FinalNewlineFormatter : DocumentFormatter
{
protected override string FormatWarningDescription => Resources.Fix_final_newline;

public override FixCategory Category => FixCategory.Whitespace;

internal override async Task<SourceText> FormatFileAsync(
Document document,
SourceText sourceText,
Expand Down
5 changes: 5 additions & 0 deletions src/Formatters/ICodeFormatter.cs
Expand Up @@ -10,6 +10,11 @@ namespace Microsoft.CodeAnalysis.Tools.Formatters
{
internal interface ICodeFormatter
{
/// <summary>
/// Gets the fix category this formatter belongs to.
/// </summary>
FixCategory Category { get; }

/// <summary>
/// Applies formatting and returns a formatted <see cref="Solution"/>.
/// </summary>
Expand Down

0 comments on commit 6e49a72

Please sign in to comment.