Skip to content
Draft
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
3 changes: 3 additions & 0 deletions CSharpier.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeStyle/CSharpUsing/AddImportsToDeepestScope/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EUnitTestFramework_002EMigrations_002EEnableDisabledProvidersMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/UnitTesting/DisabledProviders/=Testing_0020Platform/@EntryIndexedValue">False</s:Boolean>

<s:Boolean x:Key="/Default/UserDictionary/Words/=Concated/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=csharpier/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=csharpierignore/@EntryIndexedValue">True</s:Boolean>
Expand Down
5 changes: 4 additions & 1 deletion Src/CSharpier.Cli/CommandLineFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,10 @@ CancellationToken cancellationToken
{
IFormattingValidator? formattingValidator = null;

if (printerOptions.Formatter is Formatter.CSharp or Formatter.CSharpScript)
if (
printerOptions.Formatter is Formatter.CSharp or Formatter.CSharpScript
&& fileToFormatInfo.FileContents != codeFormattingResult.Code
)
{
var sourceCodeKind =
printerOptions.Formatter is Formatter.CSharpScript
Expand Down
24 changes: 22 additions & 2 deletions Src/CSharpier.Cli/EditorConfig/EditorConfigSections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ internal class EditorConfigSections
printerOptions.EndOfLine = endOfLine;
}

if (resolvedConfiguration.XmlWhitespaceSensitivity is { } xmlWhitespaceSensitivity)
{
printerOptions.XmlWhitespaceSensitivity = xmlWhitespaceSensitivity;
}

return printerOptions;
}

Expand All @@ -63,6 +68,7 @@ private class ResolvedConfiguration
public int? TabWidth { get; }
public int? MaxLineLength { get; }
public EndOfLine? EndOfLine { get; }
public XmlWhitespaceSensitivity? XmlWhitespaceSensitivity { get; set; }
public string? Formatter { get; }

public ResolvedConfiguration(List<Section> sections)
Expand Down Expand Up @@ -104,9 +110,23 @@ public ResolvedConfiguration(List<Section> sections)
}

var endOfLine = sections.LastOrDefault(o => o.EndOfLine != null)?.EndOfLine;
if (Enum.TryParse(endOfLine, true, out EndOfLine result))
if (Enum.TryParse(endOfLine, true, out EndOfLine parsedEndOfLine))
{
this.EndOfLine = parsedEndOfLine;
}

var xmlWhitespaceSensitivity = sections
.LastOrDefault(o => o.XmlWhitespaceSensitivity != null)
?.XmlWhitespaceSensitivity;
if (
Enum.TryParse(
xmlWhitespaceSensitivity,
true,
out XmlWhitespaceSensitivity parsedXmlWhitespaceSensitivity
)
)
{
this.EndOfLine = result;
this.XmlWhitespaceSensitivity = parsedXmlWhitespaceSensitivity;
}

this.Formatter = sections.LastOrDefault(o => o.Formatter is not null)?.Formatter;
Expand Down
2 changes: 2 additions & 0 deletions Src/CSharpier.Cli/EditorConfig/Section.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ internal class Section(SectionData section, string directory)
public string? MaxLineLength { get; } = section.Keys["max_line_length"];
public string? EndOfLine { get; } = section.Keys["end_of_line"];
public string? Formatter { get; } = section.Keys["csharpier_formatter"];
public string? XmlWhitespaceSensitivity { get; } =
section.Keys["csharpier_xml_whitespace_sensitivity"];

public bool IsMatch(string fileName, bool ignoreDirectory)
{
Expand Down
15 changes: 13 additions & 2 deletions Src/CSharpier.Cli/IgnoreFile.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Concurrent;
using System.IO.Abstractions;
using CSharpier.Cli.DotIgnore;
using CSharpier.Core;
Expand Down Expand Up @@ -35,17 +36,27 @@ public bool IsIgnored(string filePath)
string baseDirectoryPath,
IFileSystem fileSystem,
string? ignorePath,
ConcurrentDictionary<string, IgnoreList>? ignoreCache,
CancellationToken cancellationToken
)
{
Task<IgnoreList> CreateIgnore(string ignoreFilePath, string? overrideBasePath)
async Task<IgnoreList> CreateIgnore(string ignoreFilePath, string? overrideBasePath)
{
return IgnoreList.CreateAsync(
if (ignoreCache is not null && ignoreCache.TryGetValue(ignoreFilePath, out var ignore))
{
return ignore;
}

ignore = await IgnoreList.CreateAsync(
fileSystem,
overrideBasePath ?? Path.GetDirectoryName(ignoreFilePath)!,
ignoreFilePath,
cancellationToken
);

ignoreCache?[ignoreFilePath] = ignore;

return ignore;
}

return await SharedFunc<IgnoreFile?>
Expand Down
10 changes: 10 additions & 0 deletions Src/CSharpier.Cli/Options/ConfigurationFileOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ internal class ConfigurationFileOptions
public int? IndentSize { get; init; }
public bool UseTabs { get; init; }

[JsonConverter(typeof(CaseInsensitiveEnumConverter<XmlWhitespaceSensitivity>))]
public XmlWhitespaceSensitivity XmlWhitespaceSensitivity { get; init; } =
XmlWhitespaceSensitivity.Strict;

[JsonConverter(typeof(CaseInsensitiveEnumConverter<EndOfLine>))]
public EndOfLine EndOfLine { get; init; }

Expand Down Expand Up @@ -38,6 +42,7 @@ out var parsedFormatter
UseTabs = matchingOverride.UseTabs,
Width = matchingOverride.PrintWidth,
EndOfLine = matchingOverride.EndOfLine,
XmlWhitespaceSensitivity = matchingOverride.XmlWhitespaceSensitivity,
};
}

Expand All @@ -50,6 +55,7 @@ out var parsedFormatter
UseTabs = this.UseTabs,
Width = this.PrintWidth,
EndOfLine = this.EndOfLine,
XmlWhitespaceSensitivity = this.XmlWhitespaceSensitivity,
};
}

Expand All @@ -73,6 +79,10 @@ internal class Override
public int IndentSize { get; init; } = 4;
public bool UseTabs { get; init; }

[JsonConverter(typeof(CaseInsensitiveEnumConverter<XmlWhitespaceSensitivity>))]
public XmlWhitespaceSensitivity XmlWhitespaceSensitivity { get; init; } =
XmlWhitespaceSensitivity.Strict;

[JsonConverter(typeof(CaseInsensitiveEnumConverter<EndOfLine>))]
public EndOfLine EndOfLine { get; init; }

Expand Down
16 changes: 15 additions & 1 deletion Src/CSharpier.Cli/Options/OptionsProvider.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Concurrent;
using System.IO.Abstractions;
using System.Text.Json;
using CSharpier.Cli.DotIgnore;
using CSharpier.Cli.EditorConfig;
using CSharpier.Core;
using Microsoft.Extensions.Logging;
Expand All @@ -15,6 +16,7 @@ private readonly ConcurrentDictionary<
string,
CSharpierConfigData?
> csharpierConfigsByDirectory = new();
private readonly ConcurrentDictionary<string, IgnoreList> ignoreWithPathCache = new();
private readonly ConcurrentDictionary<string, IgnoreFile?> ignoreFilesByDirectory = new();
private readonly ConfigurationFileOptions? specifiedConfigFile;
private readonly EditorConfigSections? specifiedEditorConfig;
Expand Down Expand Up @@ -60,6 +62,7 @@ CancellationToken cancellationToken
directoryName,
fileSystem,
ignorePath,
null,
cancellationToken
);

Expand Down Expand Up @@ -114,6 +117,11 @@ await EditorConfigLocator.FindForDirectoryNameAsync(
CancellationToken cancellationToken
)
{
// TODO #1794 the xml whitespace should default based on the file
// possible defaults
// xaml files = xaml
// msbuild ones = ignore
// everything else = strict
if (this.specifiedConfigFile is not null)
{
return this.specifiedConfigFile.ConvertToPrinterOptions(filePath);
Expand Down Expand Up @@ -204,7 +212,13 @@ CancellationToken cancellationToken
Path.Combine(searchingDirectory, ".csharpierignore")
),
(searchingDirectory) =>
IgnoreFile.CreateAsync(searchingDirectory, this.fileSystem, null, cancellationToken)
IgnoreFile.CreateAsync(
searchingDirectory,
this.fileSystem,
null,
ignoreWithPathCache,
cancellationToken
)
);

#pragma warning disable IDE0270
Expand Down
2 changes: 2 additions & 0 deletions Src/CSharpier.Core/CSharp/CSharpFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ bool TryGetCompilationFailure(out CodeFormatterResult compilationResult)
LineEnding = lineEnding,
IndentSize = printerOptions.IndentSize,
UseTabs = printerOptions.UseTabs,
XmlWhitespaceSensitivity = XmlWhitespaceSensitivity.Strict,
},
};
var document = Node.Print(rootNode, printingContext);
Expand All @@ -181,6 +182,7 @@ bool TryGetCompilationFailure(out CodeFormatterResult compilationResult)
LineEnding = lineEnding,
IndentSize = printerOptions.IndentSize,
UseTabs = printerOptions.UseTabs,
XmlWhitespaceSensitivity = XmlWhitespaceSensitivity.Strict,
},
};
document = Node.Print(
Expand Down
92 changes: 77 additions & 15 deletions Src/CSharpier.Core/CSharp/SyntaxNodeComparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ CancellationToken cancellationToken
cSharpParseOptions,
cancellationToken: cancellationToken
);
this.CompareFunc = Compare;
}

public string CompareSource()
Expand Down Expand Up @@ -148,14 +149,16 @@ SyntaxNode formattedStart
return Equal;
}

#pragma warning disable CA1822
private CompareResult CompareLists<T>(
IReadOnlyList<T> originalList,
IReadOnlyList<T> formattedList,
Func<T, T, CompareResult> comparer,
Func<T, TextSpan> getSpan,
T originalList,
T formattedList,
Func<SyntaxToken, SyntaxToken, CompareResult> comparer,
Func<SyntaxToken, TextSpan> getSpan,
TextSpan originalParentSpan,
TextSpan newParentSpan
)
where T : IReadOnlyList<SyntaxToken>
{
for (var x = 0; x < originalList.Count || x < formattedList.Count; x++)
{
Expand All @@ -169,25 +172,71 @@ TextSpan newParentSpan
return NotEqual(getSpan(originalList[x]), newParentSpan);
}

if (
originalList[x] is SyntaxNode originalNode
&& formattedList[x] is SyntaxNode formattedNode
)
var result = comparer(originalList[x], formattedList[x]);
if (result.IsInvalid)
{
return result;
}
}

return Equal;
}
#pragma warning restore CA1822

private CompareResult CompareLists<T>(
T originalList,
T formattedList,
Func<SyntaxNode, SyntaxNode, CompareResult> comparer,
Func<SyntaxNode, TextSpan> getSpan,
TextSpan originalParentSpan,
TextSpan newParentSpan
)
where T : IReadOnlyList<SyntaxNode>
{
for (var x = 0; x < originalList.Count || x < formattedList.Count; x++)
{
if (x == originalList.Count)
{
this.originalStack.Push((originalNode, originalNode.Parent));
this.formattedStack.Push((formattedNode, formattedNode.Parent));
return NotEqual(originalParentSpan, getSpan(formattedList[x]));
}
else

if (x == formattedList.Count)
{
var result = comparer(originalList[x], formattedList[x]);
if (result.IsInvalid)
return NotEqual(getSpan(originalList[x]), newParentSpan);
}

var originalNode = originalList[x];
var formattedNode = formattedList[x];
this.originalStack.Push((originalNode, originalNode.Parent));
this.formattedStack.Push((formattedNode, formattedNode.Parent));
}

return Equal;
}

private static SyntaxToken[] AllSeparatorsButLast(in SeparatedSyntaxList<SyntaxNode> list)
{
if (list.Count <= 1)
{
return [];
}

var tokens = new SyntaxToken[list.Count - 1];
var tokenIndex = 0;

foreach (var element in list.GetWithSeparators())
{
if (element.IsToken)
{
tokens[tokenIndex++] = element.AsToken();
if (tokenIndex == tokens.Length)
{
return result;
break;
}
}
}

return Equal;
return tokens;
}

private static CompareResult NotEqual(SyntaxNode? originalNode, SyntaxNode? formattedNode)
Expand All @@ -210,6 +259,8 @@ private static CompareResult NotEqual(TextSpan? originalSpan, TextSpan? formatte
};
}

private Func<SyntaxToken, SyntaxToken, CompareResult> CompareFunc { get; }

private CompareResult Compare(SyntaxToken originalToken, SyntaxToken formattedToken)
{
return this.Compare(originalToken, formattedToken, null, null);
Expand Down Expand Up @@ -322,6 +373,17 @@ private CompareResult Compare(SyntaxTrivia originalTrivia, SyntaxTrivia formatte
: NotEqual(originalTrivia.Span, formattedTrivia.Span);
}

private bool CompareFullSpan(SyntaxNode originalStart, SyntaxNode formattedStart)
{
var originalSpan = OriginalSourceCode
.AsSpan()
.Slice(originalStart.FullSpan.Start, originalStart.FullSpan.Length);
var formattedSpan = NewSourceCode
.AsSpan()
.Slice(formattedStart.FullSpan.Start, formattedStart.FullSpan.Length);
return originalSpan == formattedSpan;
}

private static CompareResult CompareComment(
string originalComment,
string formattedComment,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static List<Doc> Print<T>(
)
where T : MemberDeclarationSyntax
{
var result = new List<Doc>();
var result = new List<Doc>(members.Count * 3);
if (!skipFirstHardLine)
{
result.Add(Doc.HardLine);
Expand Down
1 change: 1 addition & 0 deletions Src/CSharpier.Core/CSharp/SyntaxPrinter/Modifiers.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using CSharpier.Core.DocTypes;
using CSharpier.Core.Utilities;
using Microsoft.CodeAnalysis;

namespace CSharpier.Core.CSharp.SyntaxPrinter;
Expand Down
1 change: 1 addition & 0 deletions Src/CSharpier.Core/CSharp/SyntaxPrinter/PrintingContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class PrintingContextOptions
public required string LineEnding { get; init; }
public required int IndentSize { get; init; }
public required bool UseTabs { get; init; }
public required XmlWhitespaceSensitivity XmlWhitespaceSensitivity { get; init; }
}

public class PrintingContextState
Expand Down
1 change: 1 addition & 0 deletions Src/CSharpier.Core/CSharp/SyntaxPrinter/RightHandSide.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using CSharpier.Core.DocTypes;
using CSharpier.Core.Utilities;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ internal static class Argument
{
public static Doc Print(ArgumentSyntax node, PrintingContext context)
{
return Doc.Concat(PrintModifiers(node, context), Node.Print(node.Expression, context));
var modifiers = PrintModifiers(node, context);

return modifiers == Doc.Null
? Node.Print(node.Expression, context)
: Doc.Concat(modifiers, Node.Print(node.Expression, context));
}

public static Doc PrintModifiers(ArgumentSyntax node, PrintingContext context)
Expand Down
Loading