Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable jumping to "not formatted" files from VisualStudio error list #1517

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions Src/CSharpier.Cli/CommandLineFormatter.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using System.Diagnostics;
using System.IO.Abstractions;
using System.Text;
using CSharpier.Cli.Options;
using CSharpier.Utilities;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.IO.Abstractions;
using System.Text;

namespace CSharpier.Cli;

Expand Down Expand Up @@ -60,7 +60,8 @@ CancellationToken cancellationToken
{
var fileIssueLogger = new FileIssueLogger(
commandLineOptions.OriginalDirectoryOrFilePaths[0],
logger
logger,
commandLineOptions.LogFormat
);

var printerOptions = optionsProvider.GetPrinterOptionsFor(filePath);
Expand Down Expand Up @@ -231,7 +232,11 @@ await FormatPhysicalFile(
}
else if (warnForUnsupported)
{
var fileIssueLogger = new FileIssueLogger(originalFilePath, logger);
var fileIssueLogger = new FileIssueLogger(
originalFilePath,
logger,
logFormat: LogFormat.Console
);
fileIssueLogger.WriteWarning("Is an unsupported file type.");
}
}
Expand Down Expand Up @@ -307,7 +312,11 @@ CancellationToken cancellationToken
cancellationToken
);

var fileIssueLogger = new FileIssueLogger(originalFilePath, logger);
var fileIssueLogger = new FileIssueLogger(
originalFilePath,
logger,
commandLineOptions.LogFormat
);

logger.LogDebug(
commandLineOptions.Check
Expand Down
14 changes: 13 additions & 1 deletion Src/CSharpier.Cli/CommandLineOptions.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using System.CommandLine;
using Microsoft.Extensions.Logging;
using System.CommandLine;

namespace CSharpier.Cli;

internal class CommandLineOptions
{
public string[] DirectoryOrFilePaths { get; init; } = [];
public bool Check { get; init; }
public LogFormat LogFormat { get; init; }
public bool Fast { get; init; }
public bool SkipWrite { get; init; }
public bool WriteStdout { get; init; }
Expand All @@ -21,6 +22,7 @@ internal class CommandLineOptions
internal delegate Task<int> Handler(
string[] directoryOrFile,
bool check,
LogFormat logFormat,
bool fast,
bool skipWrite,
bool writeStdout,
Expand Down Expand Up @@ -52,6 +54,16 @@ public static RootCommand Create()
() => LogLevel.Information.ToString(),
"Specify the log level - Debug, Information (default), Warning, Error, None"
),
new Option<LogFormat>(
["--log-format"],
() => LogFormat.Console,
"""
Log output format
Console - Formats messages in a human readable way for console
interaction.
MsBuild - Formats messages in standard error/warning format for MSBuild.
"""
),
new Option(
["--no-cache"],
"Bypass the cache to determine if a file needs to be formatted."
Expand Down
5 changes: 3 additions & 2 deletions Src/CSharpier.Cli/ConsoleLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

namespace CSharpier.Cli;

internal class ConsoleLogger(IConsole console, LogLevel loggingLevel) : ILogger
internal class ConsoleLogger(IConsole console, LogLevel loggingLevel, LogFormat logFormat)
: ILogger
{
private static readonly object ConsoleLock = new();

Expand Down Expand Up @@ -52,7 +53,7 @@ void WriteLine(string? value = null)
{
var message = formatter(state, exception!);

if (logLevel >= LogLevel.Warning)
if (logFormat == LogFormat.Console && logLevel >= LogLevel.Warning)
{
console.ForegroundColor = GetColorLevel(logLevel);
Write($"{logLevel} ");
Expand Down
17 changes: 14 additions & 3 deletions Src/CSharpier.Cli/FileIssueLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,27 @@

namespace CSharpier.Cli;

internal class FileIssueLogger(string filePath, ILogger logger)
internal class FileIssueLogger(string filePath, ILogger logger, LogFormat logFormat)
{
public void WriteError(string value, Exception? exception = null)
{
logger.LogError(exception, $"{this.GetPath()} - {value}");
logger.LogError(exception, GetMessageTemplate(), this.GetPath(), value);
}

public void WriteWarning(string value)
{
logger.LogWarning($"{this.GetPath()} - {value}");
// TODO: add tests for "log warnings in Console / MsBuildFormat"
logger.LogWarning(GetMessageTemplate(), this.GetPath(), value);
}

private string GetMessageTemplate()
{
return logFormat switch
{
LogFormat.MsBuild => "{Path}: error: {Message}",
LogFormat.Console => "{Path} - {Message}",
_ => throw new NotImplementedException($"LogFormat: {Enum.GetName(logFormat)}"),
};
}

private string GetPath()
Expand Down
14 changes: 14 additions & 0 deletions Src/CSharpier.Cli/LogFormat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace CSharpier.Cli;

internal enum LogFormat
{
/// <summary>
/// Formats messages in a human readable way for console interaction.
/// </summary>
Console,

/// <summary>
/// Formats messages in standard error/warning format for MSBuild.
/// </summary>
MsBuild
}
9 changes: 5 additions & 4 deletions Src/CSharpier.Cli/Program.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using CSharpier.Cli.Server;
using Microsoft.Extensions.Logging;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO.Abstractions;
using System.Text;
using CSharpier.Cli.Server;
using Microsoft.Extensions.Logging;

namespace CSharpier.Cli;

Expand All @@ -23,6 +22,7 @@ public static async Task<int> Main(string[] args)
public static async Task<int> Run(
string[]? directoryOrFile,
bool check,
LogFormat logFormat,
bool fast,
bool skipWrite,
bool writeStdout,
Expand All @@ -42,7 +42,7 @@ CancellationToken cancellationToken
var actualConfigPath = string.IsNullOrEmpty(configPath) ? null : configPath;

var console = new SystemConsole();
var logger = new ConsoleLogger(console, logLevel);
var logger = new ConsoleLogger(console, logLevel, logFormat);

if (pipeMultipleFiles)
{
Expand Down Expand Up @@ -89,6 +89,7 @@ CancellationToken cancellationToken
OriginalDirectoryOrFilePaths = originalDirectoryOrFile!,
StandardInFileContents = standardInFileContents,
Check = check,
LogFormat = logFormat,
NoCache = noCache,
NoMSBuildCheck = noMSBuildCheck,
Fast = fast,
Expand Down
4 changes: 1 addition & 3 deletions Src/CSharpier.MsBuild/build/CSharpier.MsBuild.targets
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,7 @@
StdOutEncoding="utf-8"
StdErrEncoding="utf-8"
IgnoreExitCode="true"
IgnoreStandardErrorWarningFormat="true"
CustomErrorRegularExpression="^Error "
Command="&quot;$(CSharpier_dotnet_Path)&quot; exec &quot;$(CSharpierDllPath)&quot; $(CSharpierArgs) --no-msbuild-check --compilation-errors-as-warnings &quot;$(MSBuildProjectDirectory)&quot; &gt; $(NullOutput) "
Command="&quot;$(CSharpier_dotnet_Path)&quot; exec &quot;$(CSharpierDllPath)&quot; $(CSharpierArgs) --log-format msBuild --no-msbuild-check --compilation-errors-as-warnings &quot;$(MSBuildProjectDirectory)&quot; &gt; $(NullOutput) "
/>
</Target>
<!-- getting this to run a single time for projects that target multiple frameworks requires all of this
Expand Down
25 changes: 22 additions & 3 deletions Src/CSharpier.Tests/CommandLineFormatterTests.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System.IO.Abstractions.TestingHelpers;
using System.Text;
using CSharpier.Cli;
using FluentAssertions;
using Microsoft.Extensions.Logging;
using NUnit.Framework;
using System.IO.Abstractions.TestingHelpers;
using System.Text;

namespace CSharpier.Tests;

Expand Down Expand Up @@ -362,6 +362,23 @@ public void Format_Checks_Unformatted_File()
.StartWith("Error ./Unformatted.cs - Was not formatted.");
}

[Test]
public void Format_Checks_Unformatted_File_With_MsBuildFormat_Message()
{
var context = new TestContext();
const string unformattedFilePath = "Unformatted.cs";
context.WhenAFileExists(unformattedFilePath, UnformattedClassContent);

var result = Format(context, check: true, logFormat: LogFormat.MsBuild);

result.ExitCode.Should().Be(1);
context.GetFileContent(unformattedFilePath).Should().Be(UnformattedClassContent);
result
.ErrorOutputLines.First()
.Should()
.StartWith("./Unformatted.cs: error: Was not formatted.");
}

[TestCase("Src/node_modules/File.cs")]
[TestCase("node_modules/File.cs")]
[TestCase("node_modules/Folder/File.cs")]
Expand Down Expand Up @@ -750,6 +767,7 @@ private static FormatResult Format(
TestContext context,
bool skipWrite = false,
bool check = false,
LogFormat logFormat = LogFormat.Console,
bool writeStdout = false,
bool includeGenerated = false,
bool compilationErrorsAsWarnings = false,
Expand All @@ -772,7 +790,7 @@ params string[] directoryOrFilePaths
}

var fakeConsole = new TestConsole();
var testLogger = new ConsoleLogger(fakeConsole, LogLevel.Information);
var testLogger = new ConsoleLogger(fakeConsole, LogLevel.Information, logFormat);
var exitCode = CommandLineFormatter
.Format(
new CommandLineOptions
Expand All @@ -782,6 +800,7 @@ params string[] directoryOrFilePaths
OriginalDirectoryOrFilePaths = originalDirectoryOrFilePaths,
SkipWrite = skipWrite,
Check = check,
LogFormat = logFormat,
WriteStdout = writeStdout || standardInFileContents != null,
StandardInFileContents = standardInFileContents,
IncludeGenerated = includeGenerated,
Expand Down