diff --git a/JavaToCSharp.Tests/CommentTests.cs b/JavaToCSharp.Tests/CommentTests.cs index 4e1c3da..5f53ee6 100644 --- a/JavaToCSharp.Tests/CommentTests.cs +++ b/JavaToCSharp.Tests/CommentTests.cs @@ -241,4 +241,86 @@ public class Foo Assert.Equal(expected.ReplaceLineEndings(), parsed.ReplaceLineEndings()); } + + [Theory] + [InlineData("\n")] + [InlineData("\r\n")] + public void MultiLineJavadoc_ShouldConvertToXmlDoc_RegardlessOfLineEndings(string newLine) + { + // Issue #97: the Javadoc content was split on Environment.NewLine, so a Java file whose + // line endings differ from the host OS collapsed into a single unparsed line. + string javaCode = """ + package foo; + + public class Foo { + /** + * Really cool field that contains something. + * Keep in mind that this field is cooler than awesomeField. + */ + public int reallyAwesomeField; + } + """.ReplaceLineEndings(newLine); + + var options = new JavaConversionOptions(); + options.Usings.Clear(); + + var parsed = JavaToCSharpConverter.ConvertText(javaCode, options) ?? ""; + + testOutputHelper.WriteLine(parsed); + + const string expected = """ + namespace Foo + { + public class Foo + { + /// + /// Really cool field that contains something. + /// Keep in mind that this field is cooler than awesomeField. + /// + public int reallyAwesomeField; + } + } + """; + + Assert.Equal(expected.ReplaceLineEndings(), parsed.ReplaceLineEndings()); + } + + [Theory] + [InlineData("\n")] + [InlineData("\r\n")] + public void MultiLineJavadocWithTags_ShouldConvertToXmlDoc_RegardlessOfLineEndings(string newLine) + { + string javaCode = """ + package foo; + + public class Foo { + /** + * Does something useful. + * Second line of the summary. + * + * @param name the name to use + * @return the computed value + * @throws IllegalStateException if it breaks + */ + public int doIt(String name) { + return 1; + } + } + """.ReplaceLineEndings(newLine); + + var options = new JavaConversionOptions(); + options.Usings.Clear(); + + var parsed = JavaToCSharpConverter.ConvertText(javaCode, options) ?? ""; + + testOutputHelper.WriteLine(parsed); + + Assert.Contains("/// ", parsed); + Assert.Contains("/// Does something useful.", parsed); + Assert.Contains("/// Second line of the summary.", parsed); + Assert.Contains("/// ", parsed); + Assert.Contains("""/// the name to use""", parsed); + Assert.Contains("/// the computed value", parsed); + Assert.Contains("""/// if it breaks""", parsed); + } } diff --git a/JavaToCSharp/CommentsHelper.cs b/JavaToCSharp/CommentsHelper.cs index 31cafc9..e14d9e0 100644 --- a/JavaToCSharp/CommentsHelper.cs +++ b/JavaToCSharp/CommentsHelper.cs @@ -102,7 +102,7 @@ public static CompilationUnitSyntax AddPackageComments(CompilationUnitSyntax syn } else { - var commentTrivia = SyntaxFactory.SyntaxTrivia(kind, pre + comment.getContent() + post); + var commentTrivia = SyntaxFactory.SyntaxTrivia(kind, pre + NormalizeLineEndings(comment.getContent()) + post); if (pos == CommentPosition.Leading) { leadingTriviaList.Add(commentTrivia); @@ -136,13 +136,25 @@ private static SyntaxTrivia CreateNonMemberCommentTrivia(JavaComments.Comment co FormatAsBlockComment(comment.getContent()) + suffix); } - return SyntaxFactory.SyntaxTrivia(kind, pre + comment.getContent() + post + suffix); + return SyntaxFactory.SyntaxTrivia(kind, pre + NormalizeLineEndings(comment.getContent()) + post + suffix); } + /// + /// Splits text that originated from the Java source into lines. The line endings of the parsed file are + /// preserved by JavaParser and are independent of the host OS, so splitting on + /// would fail whenever the two differ (see issue #97). + /// + private static string[] SplitLines(string text) => text.ReplaceLineEndings("\n").Split('\n'); + + /// + /// Rewrites line endings that came from the Java source to the ones used for the generated C# output, so that + /// multi-line comments do not introduce line endings foreign to the rest of the file. + /// + private static string NormalizeLineEndings(string text) => text.ReplaceLineEndings(Environment.NewLine); + private static string FormatAsBlockComment(string content) { - var lines = content.ReplaceLineEndings("\n") - .Split('\n') + var lines = SplitLines(content) .Select(line => line.TrimStart().TrimStart('*').Trim()) .ToList(); @@ -293,7 +305,7 @@ public static IEnumerable ConvertToComment(IEnumerable(); foreach (var code in codes) { - string[] input = code.ToString().Split([Environment.NewLine], StringSplitOptions.None); + string[] input = SplitLines(code.ToString()); outputs.AddRange(input); } @@ -318,7 +330,7 @@ public static IEnumerable ConvertToComment(IEnumerable ConvertDocComment(JavaComments.Comment comment, string? post) { - string[] input = comment.getContent().Split([Environment.NewLine], StringSplitOptions.None); + string[] input = SplitLines(comment.getContent()); var output = new List(); var remarks = new List(); // For Java tags unknown in C# var currentOutput = output;