CSharpier is an opinionated code formatter for c#.
Previously CSharpier would only format files matching *.cs
which prevented it from formatting C# script files. It now formats *.{cs,csx}
Thanks go to @Eptagone for the suggestion
Invocation chains that started with an identifier <= 4 characters were causing a strange break in the first method call. There were other edge cases cleaned up while working on the fix.
// 0.27.0
var something________________________________________ = x.SomeProperty.CallMethod(
longParameter_____________,
longParameter_____________
)
.CallMethod();
// 0.27.1
var something________________________________________ = x
.SomeProperty.CallMethod(longParameter_____________, longParameter_____________)
.CallMethod();
// 0.27.0
var someLongValue_________________ = memberAccessExpression[
elementAccessExpression
].theMember______________________________();
// 0.27.1
var someLongValue_________________ = memberAccessExpression[elementAccessExpression]
.theMember______________________________();
// 0.27.0
someThing_______________________
?.Property
.CallMethod__________________()
.CallMethod__________________();
// 0.27.1
someThing_______________________
?.Property.CallMethod__________________()
.CallMethod__________________();
Thanks go to @Rudomitori for reporting the issue
When an interpolated raw string changed indentation due to CSharpier formatting, CSharpier was incorrectly reporting it as failing syntax tree validation.
// input
CallMethod(CallMethod(
$$"""
SomeString
""", someValue));
// output
CallMethod(
CallMethod(
$$"""
SomeString
""",
someValue
)
);
Thanks go to @Rudomitori for reporting the issue
The GRPC support added in 0.27.0 increased the size of the nuget package significantly and has been removed.
CSharpier can now start a kestrel web server to support communication with the extensions once they are all updated.
Full Changelog: https://github.com/belav/csharpier/compare/0.27.0...0.27.1
Many thanks go to @Rudomitori for contributing a number of improvements to the formatting of lambda expressions.
Some examples of the improvements.
// input
var affectedRows = await _dbContext.SomeEntities
.ExecuteUpdateAsync(
x =>
x.SetProperty(x => x.Name, x => command.NewName)
.SetProperty(x => x.Title, x => command.NewTItle)
.SetProperty(x => x.Count, x => x.Command.NewCount)
);
// 0.27.0
var affectedRows = await _dbContext.SomeEntities
.ExecuteUpdateAsync(x =>
x.SetProperty(x => x.Name, x => command.NewName)
.SetProperty(x => x.Title, x => command.NewTItle)
.SetProperty(x => x.Count, x => x.Command.NewCount)
);
// input
builder.Entity<IdentityUserToken<string>>(b =>
{
b.HasKey(
l =>
new
{
l.UserId,
l.LoginProvider,
l.Name
}
);
b.ToTable("AspNetUserTokens");
});
// 0.27.0
builder.Entity<IdentityUserToken<string>>(b =>
{
b.HasKey(l => new
{
l.UserId,
l.LoginProvider,
l.Name
});
b.ToTable("AspNetUserTokens");
});
// input
table.PrimaryKey(
"PK_AspNetUserTokens",
x =>
new
{
x.UserId,
x.LoginProvider,
x.Name
}
);
// 0.27.0
table.PrimaryKey(
"PK_AspNetUserTokens",
x => new
{
x.UserId,
x.LoginProvider,
x.Name
}
);
readonly ref
is changed to ref readonly
causing error CS9190 #1123CSharpier was sorting modifiers in all places they occurred. Resulting the following change that led to code that would not compile.
// input
void Method(ref readonly int someParameter) { }
// 0.26.7
void Method(readonly ref int someParameter) { }
// 0.27.0
void Method(ref readonly int someParameter) { }
Thanks go to @aurnoi1 for reporting the bug
When a collection expression contained a directive immediately before the closing bracket, that directive was not included in the output.
// input
int[] someArray =
[
1
#if DEBUG
,
2
#endif
];
// 0.26.7
int[] someArray = [1];
// 0.27.0
int[] someArray =
[
1
#if DEBUG
,
2
#endif
];
Thanks go to @Meowtimer for reporting the bug
CSharpier.MsBuild made an assumption that the project being built would be built using net6-net8 and failed when the project was built with earlier versions of dotnet.
It now falls back to trying to use net8
Thanks go to @samtrion for the contribution
Large object initializers now retain single empty lines between initializers.
vvar someObject = new SomeObject
{
NoLineAllowedAboveHere = 1,
ThisLineIsOkay = 2,
// comment
AndThisLine = 3,
DontAddLines = 4,
};
Thanks go to @Qtax for the suggestion
By default CSharpier will not format files that were generated by the SDK, or files that begin with <autogenerated />
comments.
Passing the option --include-generated
to the CLI will cause those files to be formatted.
CSharpier now adjusts the indentation of raw string literals if the end delimiter is indented.
// input
var someString = """
Indent based on previous line
""";
var doNotIndentIfEndDelimiterIsAtZero = """
Keep This
Where It
Is
""";
// 0.26.7
var someString = """
Indent based on previous line
""";
var doNotIndentIfEndDelimiterIsAtZero = """
Keep This
Where It
Is
""";
// 0.27.0
var someString = """
Indent based on previous line
""";
var doNotIndentIfEndDelimiterIsAtZero = """
Keep This
Where It
Is
""";
Thanks go to @jods4 for reporting the issue
CSharpier was not properly indenting an invocation chain when it was being split by comments.
// input
var someValue =
// Some Comment
CallSomeMethod()
// Another Comment
.CallSomeMethod();
// 0.26.7
var someValue =
// Some Comment
CallSomeMethod()
// Another Comment
.CallSomeMethod();
// 0.27.0
var someValue =
// Some Comment
CallSomeMethod()
// Another Comment
.CallSomeMethod();
Thanks go to @tyrrrz for reporting the issue
Currently the extensions for CSharpier send data to a running instance of CSharpier by piping stdin/stdout back and forth. This approach has proved problematic and hard to extend.
As of 0.27.0, CSharpier can run a GRPC server to allow communication with the extensions once they are all updated.
Full Changelog: https://github.com/belav/csharpier/compare/0.26.7...0.27.0
0.26.0 introduced changes that broke long invocation chains on fields/properties as well as methods. That change has been reverted after community feedback.
// 0.26.0
var loggerConfiguration = new LoggerConfiguration()
.Enrich
.FromLogContext()
.Enrich
.WithProperty("key", "value")
.Enrich
.WithProperty("key", "value")
.Enrich
.WithProperty("key", "value")
.Enrich
.WithProperty("key", "value")
.WriteTo
.Console(outputTemplate: "template");
// 0.26.7
var loggerConfiguration = new LoggerConfiguration()
.Enrich.FromLogContext()
.Enrich.WithProperty("key", "value")
.Enrich.WithProperty("key", "value")
.Enrich.WithProperty("key", "value")
.Enrich.WithProperty("key", "value")
.WriteTo.Console(outputTemplate: "template");
Full Changelog: https://github.com/belav/csharpier/compare/0.26.6...0.26.7
If CSharpier was validating that a file was formatted, and that file contained only \n
but CSharpier was configured to use \r\n
, then it would report the problem as The file did not end with a single newline
CSharpier added support for reading line ending configuration from an .editorconfig
which could contain end_of_line = crlf
so some users were unknowingly configuring CSharpier to use \r\n
CSharpier now correctly reports the problem as The file contained different line endings than formatting it would result in.
Full Changelog: https://github.com/belav/csharpier/compare/0.26.5...0.26.6
NSubstitute
before Newtonsoft.Json
#1061The using sorting in 0.26.4
was taking into account case.
// 0.26.4
using System;
using NSubstitute;
using Newtonsoft.Json;
// 0.26.5
using System;
using Newtonsoft.Json;
using NSubstitute;
Thanks go to @loraderon for contributing the fix.
A collection expression in a property initializer was including an extra new line.
// 0.26.4
public class ClassName
{
public List<DayOfWeek> DaysOfWeek { get; } =
[
DayOfWeek.Sunday,
// snip
DayOfWeek.Saturday
];
}
// 0.26.5
public class ClassName
{
public List<DayOfWeek> DaysOfWeek { get; } =
[
DayOfWeek.Sunday,
// snip
DayOfWeek.Saturday
];
}
Thanks go to @SapiensAnatis for contributing the fix.
When the close bracket on a collection expression had a leading comment, it had the same indentation as the bracket.
// 0.26.4
host.AddSection(
name: "Kontakt Libraries (Third Party)",
tags: Tags.SamplesUsed,
tasks:
[
// TODO: Add any used third party instruments below as you discover them.
]
);
// 0.26.5
host.AddSection(
name: "Kontakt Libraries (Third Party)",
tags: Tags.SamplesUsed,
tasks:
[
// TODO: Add any used third party instruments below as you discover them.
]
);
Thanks go to @fgimian for reporting the problem
Full Changelog: https://github.com/belav/csharpier/compare/0.26.4...0.26.5
There were a number of cases where CSharpier was including extra blank lines, an extra space, or not formatting contents of collection expressions.
// 0.26.3
var a = new A { B = [1, 2, 3] };
List<string> items = [// My item
"Hello",];
items.AddRange(
[
LongValue________________________________________________,
LongValue________________________________________________
]
);
items = [];
items ??= [];
class SomeClass
{
public SomeValue SomeProperty =>
[
LongValue________________________________________________,
LongValue________________________________________________
];
public SomeValue Method() =>
[
LongValue________________________________________________,
LongValue________________________________________________
];
}
// 0.26.4
var a = new A { B = [1, 2, 3] };
List<string> items =
[
// My item
"Hello",
];
items.AddRange(
[
LongValue________________________________________________,
LongValue________________________________________________
]
);
items = [];
items ??= [];
class SomeClass
{
public SomeValue SomeProperty =>
[
LongValue________________________________________________,
LongValue________________________________________________
];
public SomeValue Method() =>
[
LongValue________________________________________________,
LongValue________________________________________________
];
}
Thanks go to @fgimian and @JoshWoodArup for reporting the issues
The sorting of Usings was done in a culture specific manner, resulting in unexpected behavior.
In Czech (cs-CZ) the ch
is a "single letter" which is placed between h
and i
, which resulted in the following sorting behavior.
// 0.26.3
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Channel;
// 0.26.4
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
Thanks go to @davidkudera for the contribution
// 0.26.0
List<int> ids = [];
// 0.26.3
List<int> ids = [];
Thanks go to @Jackenmen for reporting the problem.
// 0.26.0
List<int> ids = [ ];
List<int> ids = [ 1, 2, 3 ];
// 0.26.3
List<int> ids = [];
List<int> ids = [1, 2, 3];
Thanks go to @golavr for reporting the problem.
When piping a file to csharpier via stdin, CSharpier uses the working directory to locate any configuration files. This was broken with 0.26.0
.
Thanks go to @kikniknik for reporting the problem.
Previously CSharpier.MSBuild was using targetFramework
to determine which version of CSharpier to run. This was problematic when there were multiple target frameworks, or the project was targeting a superset such as net8.0-windows
It now makes use of NETCoreSdkVersion
to determine which version of CSharpier to run.
Thanks go to @Tyrrrz for the suggestion and to @Cjewett for the contribution to make it work
When looking for .editorconfig
files, CSharpier looks for them recursively in the current directory. This logic was not taking into account any files or directories ignored by a .csharpierignore
.
Thanks go to @sebastieng84 for the contribution.
CSharpier now only looks for an .editorconfig
for the file being piped to CSharpier. Under normal usage it recursively looks for all possible .editorconfig
files for the given directory.
Full Changelog: https://github.com/belav/csharpier/compare/0.26.2...0.26.3
Improves error handling and reports when it is not possible to get CSharpier started to format files. Deals with the githash in version numbers correctly.
When using CSharpier.MsBuild in a setting where the project targeted net8.0 and only the net8 sdk was installed, CSharpier.MsBuild would attempt to run the net7.0 version of csharpier and fail because the net7 sdk was not installed.
Thanks go to @aditnryn for the fix
Global using were not sorting System
to the top, which was inconsistent with regular using.
// 0.26.1
global using ZWord;
global using AWord;
global using System.Web;
global using System;
// 0.26.2
global using System;
global using System.Web;
global using AWord;
global using ZWord;
Thanks go to @vipentti for the fix
Full Changelog: https://github.com/belav/csharpier/compare/0.26.1...0.26.2
CSharpier was unable to parse an .editorconfig
file that contained duplicate sections and would crash. This would result in a hung IDE.
[*]
insert_final_newline = true
[*]
spelling_languages = en-us
Thanks go to @echoix for helping track this down.
Given the following setup
/src/.editorconfig
/src/ProjectName/.editorconfig
/src/.csharpierrc
Originally with 0.26.0, the /src/ProjectName/.editorconfig
file would be used for determining the configuration options for a file within src/ProjectName
. This resulted in the existing options within .csharpierrc
being ignored.
With 0.26.1, if a .csharpierrc
exists anywhere above a given file, it will be used to determine the configuration options.
Thanks go to @parched for reporting the issue.
Full Changelog: https://github.com/belav/csharpier/compare/0.26.0...0.26.1