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

Generate code with consistent line endings #412

Merged
merged 1 commit into from
Sep 18, 2021
Merged
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
2 changes: 1 addition & 1 deletion src/Microsoft.Windows.CsWin32/FastSyntaxFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ internal static SeparatedSyntaxList<TNode> SeparatedList<TNode>()

internal static SyntaxToken Literal(char value) => SyntaxFactory.Literal(TriviaList(), SymbolDisplay.FormatLiteral(value, quote: true), value, TriviaList());

internal static SyntaxTriviaList ParseLeadingTrivia(string text) => SyntaxFactory.ParseLeadingTrivia(text);
internal static SyntaxTriviaList ParseLeadingTrivia(string text) => SyntaxFactory.ParseLeadingTrivia(text.Replace("\r\n", "\n"));

internal static IdentifierNameSyntax IdentifierName(string name) => SyntaxFactory.IdentifierName(Identifier(name));

Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.Windows.CsWin32/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public class Generator : IDisposable
");

private static readonly XmlTextSyntax DocCommentStart = XmlText(" ").WithLeadingTrivia(DocumentationCommentExterior("///"));
private static readonly XmlTextSyntax DocCommentEnd = XmlText(XmlTextNewLine("\r\n", continueXmlDocumentationComment: false));
private static readonly XmlTextSyntax DocCommentEnd = XmlText(XmlTextNewLine("\n", continueXmlDocumentationComment: false));

private static readonly SyntaxToken SemicolonWithLineFeed = TokenWithLineFeed(SyntaxKind.SemicolonToken);
private static readonly IdentifierNameSyntax ConstantsClassName = IdentifierName("Constants");
Expand Down
35 changes: 35 additions & 0 deletions test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Testing;
using Microsoft.CodeAnalysis.Text;
using Microsoft.Windows.CsWin32;
using Microsoft.Windows.CsWin32.Tests;
using Xunit;
Expand Down Expand Up @@ -2170,6 +2171,38 @@ static string JoinAssemblyMetadata(string name)

private static IEnumerable<AttributeSyntax> FindAttribute(SyntaxList<AttributeListSyntax> attributeLists, string name) => attributeLists.SelectMany(al => al.Attributes).Where(a => a.Name.ToString() == name);

private static void AssertConsistentLineEndings(Compilation compilation)
{
foreach (SyntaxTree doc in compilation.SyntaxTrees)
{
AssertConsistentLineEndings(doc);
}
}

private static void AssertConsistentLineEndings(SyntaxTree syntaxTree)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 You could use the new EqualOrDiff functionality from dotnet/roslyn-sdk for this assertion by asserting the syntaxTree.GetText() is the same as syntaxTree.GetText().Replace("\r\n", "\n").

dotnet/roslyn-sdk#886

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh, that's nice. Thanks for the tip. Where is this EqualOrDiff method exposed, or would I need to copy its source?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you already reference MS.CA.Testing, you can use DefaultVerifier with this extension method. Otherwise the source is reasonably easy to copy.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that EqualOrDiff was originally implemented by you, but we modified it in dotnet/roslyn-sdk#878 and dotnet/roslyn-sdk#886 to specifically support cases where only the line endings changed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya, I thought I remembered that I had shared it. We developed it for vs-mef.

{
SourceText sourceText = syntaxTree.GetText();
int firstLineBreakLength = default;
int lineCount = 1;
foreach (TextLine line in sourceText.Lines)
{
int thisLineBreakLength = line.EndIncludingLineBreak - line.End;
if (lineCount == 1)
{
firstLineBreakLength = thisLineBreakLength;
}
else
{
if (firstLineBreakLength != thisLineBreakLength && thisLineBreakLength > 0)
{
Assert.False(true, $"{syntaxTree.FilePath} Line {lineCount} had a {thisLineBreakLength}-byte line ending but line 1's line ending was {firstLineBreakLength} bytes long.");
}
}

lineCount++;
}
}

private CSharpCompilation AddGeneratedCode(CSharpCompilation compilation, Generator generator)
{
var compilationUnits = generator.GetCompilationUnits(CancellationToken.None);
Expand Down Expand Up @@ -2232,6 +2265,8 @@ private void AssertNoDiagnostics(CSharpCompilation compilation, bool logAllGener
Assert.Empty(emitDiagnostics);
Assert.True(emitSuccessful);
}

AssertConsistentLineEndings(compilation);
}

private void LogDiagnostics(ImmutableArray<Diagnostic> diagnostics)
Expand Down