diff --git a/JavaToCSharp.Tests/CommentTests.cs b/JavaToCSharp.Tests/CommentTests.cs index c60d636e..3bd5514f 100644 --- a/JavaToCSharp.Tests/CommentTests.cs +++ b/JavaToCSharp.Tests/CommentTests.cs @@ -1,4 +1,3 @@ -using Microsoft.CodeAnalysis.CSharp; using Xunit.Abstractions; namespace JavaToCSharp.Tests; diff --git a/JavaToCSharp.Tests/JavaToCSharp.Tests.csproj b/JavaToCSharp.Tests/JavaToCSharp.Tests.csproj index 54e5aede..51827f4d 100644 --- a/JavaToCSharp.Tests/JavaToCSharp.Tests.csproj +++ b/JavaToCSharp.Tests/JavaToCSharp.Tests.csproj @@ -6,7 +6,7 @@ enable latest enable - nullable + true @@ -26,7 +26,7 @@ - + diff --git a/JavaToCSharp.sln b/JavaToCSharp.sln deleted file mode 100644 index ca90a449..00000000 --- a/JavaToCSharp.sln +++ /dev/null @@ -1,55 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.6.33829.357 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JavaToCSharp", "JavaToCSharp\JavaToCSharp.csproj", "{EDCE2F7C-299E-4FEA-870F-87C201FB2E43}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lib", "Lib", "{7A18D136-8A66-4B98-8D8E-9C210E0C8D2D}" - ProjectSection(SolutionItems) = preProject - Lib\javaparser-core-3.25.4.jar = Lib\javaparser-core-3.25.4.jar - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JavaToCSharpCli", "JavaToCSharpCli\JavaToCSharpCli.csproj", "{8C56AE52-8E0F-438F-9B5B-87B891D70861}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JavaToCSharpGui", "JavaToCSharpGui\JavaToCSharpGui.csproj", "{DAA3F412-0460-40C3-98F7-3244649820F9}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E8E0DCFE-ED61-442C-9F4B-36433D6949DF}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JavaToCSharp.Tests", "JavaToCSharp.Tests\JavaToCSharp.Tests.csproj", "{0CBBEF05-FD79-474A-A5F0-25B341B8B77D}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {EDCE2F7C-299E-4FEA-870F-87C201FB2E43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EDCE2F7C-299E-4FEA-870F-87C201FB2E43}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EDCE2F7C-299E-4FEA-870F-87C201FB2E43}.Release|Any CPU.Build.0 = Release|Any CPU - {EDCE2F7C-299E-4FEA-870F-87C201FB2E43}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8C56AE52-8E0F-438F-9B5B-87B891D70861}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8C56AE52-8E0F-438F-9B5B-87B891D70861}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8C56AE52-8E0F-438F-9B5B-87B891D70861}.Release|Any CPU.Build.0 = Release|Any CPU - {8C56AE52-8E0F-438F-9B5B-87B891D70861}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DAA3F412-0460-40C3-98F7-3244649820F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DAA3F412-0460-40C3-98F7-3244649820F9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DAA3F412-0460-40C3-98F7-3244649820F9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DAA3F412-0460-40C3-98F7-3244649820F9}.Release|Any CPU.Build.0 = Release|Any CPU - {0CBBEF05-FD79-474A-A5F0-25B341B8B77D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0CBBEF05-FD79-474A-A5F0-25B341B8B77D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0CBBEF05-FD79-474A-A5F0-25B341B8B77D}.Release|Any CPU.Build.0 = Release|Any CPU - {0CBBEF05-FD79-474A-A5F0-25B341B8B77D}.Debug|Any CPU.Build.0 = Debug|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {EB538484-5025-4753-B0A5-2C66A6C06193} - EndGlobalSection -EndGlobal diff --git a/JavaToCSharp.slnx b/JavaToCSharp.slnx new file mode 100644 index 00000000..a964be56 --- /dev/null +++ b/JavaToCSharp.slnx @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/JavaToCSharp.sln.DotSettings b/JavaToCSharp.slnx.DotSettings similarity index 65% rename from JavaToCSharp.sln.DotSettings rename to JavaToCSharp.slnx.DotSettings index 9e8d4492..fb2552b8 100644 --- a/JavaToCSharp.sln.DotSettings +++ b/JavaToCSharp.slnx.DotSettings @@ -1,5 +1,7 @@  <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="_" Suffix="" Style="aaBb" /></Policy> + True True True True diff --git a/JavaToCSharp/CommentsHelper.cs b/JavaToCSharp/CommentsHelper.cs index a0b74b97..06da9c9f 100644 --- a/JavaToCSharp/CommentsHelper.cs +++ b/JavaToCSharp/CommentsHelper.cs @@ -1,15 +1,15 @@ -using Microsoft.CodeAnalysis; +using System.Text.RegularExpressions; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using JavaAst = com.github.javaparser.ast; using JavaComments = com.github.javaparser.ast.comments; using JavaParser = com.github.javaparser; -using SysRegex = System.Text.RegularExpressions; namespace JavaToCSharp; -public static class CommentsHelper +public static partial class CommentsHelper { private enum CommentPosition { @@ -18,8 +18,8 @@ private enum CommentPosition } // Regex: Optional *, capture optional @par, capture optional text (keep leading whitespaces, trim end). - private static readonly SysRegex.Regex _analyzeDocString = - new(@"^(\s*\*)?(\s*(?@[a-z]+))?\s?(?.*?)\s*$", SysRegex.RegexOptions.Compiled); + [GeneratedRegex(@"^(\s*\*)?(\s*(?@[a-z]+))?\s?(?.*?)\s*$", RegexOptions.Compiled)] + private static partial Regex AnalyzeDocStringRegex { get; } private static readonly Dictionary _knownTagsDict = new() { @@ -142,9 +142,14 @@ private static (SyntaxKind kind, string? pre, string? post) GetCommentInfo( private static List<(JavaComments.Comment c, CommentPosition pos)> GatherComments(JavaAst.Node? node) { var result = new List<(JavaComments.Comment c, CommentPosition pos)>(); - if (node == null) return result; + + if (node is null) + { + return result; + } var parentNode = node.getParentNode().FromOptional(); + if (parentNode is null) { if (node.getComment().FromOptional() is { } comment) @@ -155,6 +160,7 @@ private static (SyntaxKind kind, string? pre, string? post) GetCommentInfo( else { var unsortedComments = parentNode.getAllContainedComments(); + if (unsortedComments.size() != 0) { var comments = unsortedComments.OfType() @@ -163,7 +169,7 @@ private static (SyntaxKind kind, string? pre, string? post) GetCommentInfo( .ToList(); // Find leading comments - var nodeBegin = node.getBegin().FromOptional() + var nodeBegin = node.getBegin().FromOptional() ?? throw new InvalidOperationException("Node did not have a begin position"); var previousSibling = GetPreviousSibling(parentNode, nodeBegin); int previousPos = previousSibling?.getEnd().FromOptional()?.line ?? 0; @@ -173,7 +179,7 @@ private static (SyntaxKind kind, string? pre, string? post) GetCommentInfo( // Find trailing comments. // We consider only comments either appearing on the same line or, if no sibling nodes follow, // then also comments on the succeeding lines (because otherwise they belong to the next sibling). - var nodeEnd = node.getEnd().FromOptional() + var nodeEnd = node.getEnd().FromOptional() ?? throw new InvalidOperationException("Node did not have an end position"); var trailingComments = HasNextSibling(parentNode, nodeEnd) @@ -191,7 +197,7 @@ private static (SyntaxKind kind, string? pre, string? post) GetCommentInfo( comments.Where(c => { var commentBegin = c.getBegin().FromOptional(); - return commentBegin != null && (commentBegin.line == nodeEnd.line && commentBegin.column > nodeEnd.column || commentBegin.line > nodeEnd.line); + return commentBegin is not null && (commentBegin.line == nodeEnd.line && commentBegin.column > nodeEnd.column || commentBegin.line > nodeEnd.line); }) .Select(c => (c, CommentPosition.Trailing)); @@ -200,7 +206,7 @@ private static (SyntaxKind kind, string? pre, string? post) GetCommentInfo( .Where(c => { var commentBegin = c.getBegin().FromOptional(); - return commentBegin != null && commentBegin.line == nodeEnd.line && commentBegin.column > nodeEnd.column; + return commentBegin is not null && commentBegin.line == nodeEnd.line && commentBegin.column > nodeEnd.column; }) .Select(c => (c, CommentPosition.Trailing)); @@ -212,7 +218,7 @@ private static bool HasNextSibling(JavaAst.Node parentNode, JavaParser.Position .Any(sibling => { var siblingBegin = sibling.getBegin().FromOptional(); - return siblingBegin != null && (siblingBegin.line > nodeEnd.line || siblingBegin.line == nodeEnd.line && siblingBegin.column > nodeEnd.column); + return siblingBegin is not null && (siblingBegin.line > nodeEnd.line || siblingBegin.line == nodeEnd.line && siblingBegin.column > nodeEnd.column); }); } @@ -222,7 +228,7 @@ private static bool HasNextSibling(JavaAst.Node parentNode, JavaParser.Position { var commentBegin = c.getBegin().FromOptional(); var commentEnd = c.getEnd().FromOptional(); - return commentBegin != null && commentEnd != null && commentBegin.line > previousPos && (commentEnd.line < nodeBegin.line || commentEnd.line == nodeBegin.line && commentEnd.column < nodeBegin.column); + return commentBegin is not null && commentEnd is not null && commentBegin.line > previousPos && (commentEnd.line < nodeBegin.line || commentEnd.line == nodeBegin.line && commentEnd.column < nodeBegin.column); }) .Select(c => (c, CommentPosition.Leading)); } @@ -236,7 +242,7 @@ private static bool HasNextSibling(JavaAst.Node parentNode, JavaParser.Position .LastOrDefault(sibling => { var siblingEnd = sibling.getEnd().FromOptional(); - return siblingEnd != null && (siblingEnd.line < nodeBegin.line || siblingEnd.line == nodeBegin.line && siblingEnd.column < nodeBegin.column); + return siblingEnd is not null && (siblingEnd.line < nodeBegin.line || siblingEnd.line == nodeBegin.line && siblingEnd.column < nodeBegin.column); }); } @@ -252,7 +258,7 @@ public static IEnumerable ConvertToComment(IEnumerable(); foreach (var code in codes) { - string[] input = code.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None); + string[] input = code.ToString().Split([Environment.NewLine], StringSplitOptions.None); outputs.AddRange(input); } @@ -277,14 +283,14 @@ public static IEnumerable ConvertToComment(IEnumerable ConvertDocComment(JavaComments.Comment comment, string? post) { - string[] input = comment.getContent().Split(new[] { Environment.NewLine }, StringSplitOptions.None); + string[] input = comment.getContent().Split([Environment.NewLine], StringSplitOptions.None); var output = new List(); var remarks = new List(); // For Java tags unknown in C# var currentOutput = output; string? tag = null; foreach (string inputLine in input) { - var match = _analyzeDocString.Match(inputLine); + var match = AnalyzeDocStringRegex.Match(inputLine); if (match.Success) { string paramName = match.Groups["param"].Value; @@ -304,7 +310,7 @@ private static IEnumerable ConvertDocComment(JavaComments.Comment remarks.Add(paramName + text); tag = "remarks"; } - else if (tag == null) + else if (tag is null) { tag = "summary"; OpenSection(output, tag, text); @@ -358,14 +364,14 @@ private static void CloseSection(IList output, string? tag) } else { - output[output.Count - 1] += xmlEndTag; + output[^1] += xmlEndTag; } } } private static void TrimTrailingEmptyLines(IList lines) { - while (lines.Count > 0 && lines[lines.Count - 1].Trim() == "") + while (lines.Count > 0 && lines[^1].Trim() == "") { lines.RemoveAt(lines.Count - 1); } @@ -468,7 +474,7 @@ private static SyntaxNode AdjustBlockCommentIndentation(SyntaxNode node) if (t.IsKind(SyntaxKind.MultiLineCommentTrivia)) { int indentation = GetIndentation(leading, i) + 1; // Add one to align stars. - string[] lines = t.ToFullString().Split(new[] { Environment.NewLine }, StringSplitOptions.None); + string[] lines = t.ToFullString().Split([Environment.NewLine], StringSplitOptions.None); string indentString = new(' ', indentation); for (int l = 1; l < lines.Length; l++) { diff --git a/JavaToCSharp/ConversionContext.cs b/JavaToCSharp/ConversionContext.cs index a93053b7..2f565f24 100644 --- a/JavaToCSharp/ConversionContext.cs +++ b/JavaToCSharp/ConversionContext.cs @@ -1,22 +1,14 @@ -using System.Collections.Generic; -using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Syntax; namespace JavaToCSharp; -public class ConversionContext +public class ConversionContext(JavaConversionOptions options) { - public ConversionContext(JavaConversionOptions options) - { - PendingAnonymousTypes = new Queue(); - UsedAnonymousTypeNames = new HashSet(); - Options = options; - } + public Queue PendingAnonymousTypes { get; } = new(); - public Queue PendingAnonymousTypes { get; } + public ISet UsedAnonymousTypeNames { get; } = new HashSet(); - public ISet UsedAnonymousTypeNames { get; } - - public JavaConversionOptions Options { get; } + public JavaConversionOptions Options { get; } = options; public string? RootTypeName { get; set; } diff --git a/JavaToCSharp/ConversionStateChangedEventArgs.cs b/JavaToCSharp/ConversionStateChangedEventArgs.cs index d632e0b9..b69d8e2d 100644 --- a/JavaToCSharp/ConversionStateChangedEventArgs.cs +++ b/JavaToCSharp/ConversionStateChangedEventArgs.cs @@ -1,13 +1,6 @@ -using System; +namespace JavaToCSharp; -namespace JavaToCSharp; - -public sealed class ConversionStateChangedEventArgs : EventArgs +public sealed class ConversionStateChangedEventArgs(ConversionState newState) : EventArgs { - public ConversionStateChangedEventArgs(ConversionState newState) - { - NewState = newState; - } - - public ConversionState NewState { get; } + public ConversionState NewState { get; } = newState; } diff --git a/JavaToCSharp/ConversionWarningEventArgs.cs b/JavaToCSharp/ConversionWarningEventArgs.cs index 5313a511..dca58057 100644 --- a/JavaToCSharp/ConversionWarningEventArgs.cs +++ b/JavaToCSharp/ConversionWarningEventArgs.cs @@ -1,16 +1,8 @@ -using System; +namespace JavaToCSharp; -namespace JavaToCSharp; - -public class ConversionWarningEventArgs : EventArgs +public class ConversionWarningEventArgs(string message, int javaLineNumber) : EventArgs { - public ConversionWarningEventArgs(string message, int javaLineNumber) - { - Message = message; - JavaLineNumber = javaLineNumber; - } - - public string Message { get; } + public string Message { get; } = message; - public int JavaLineNumber { get; } + public int JavaLineNumber { get; } = javaLineNumber; } diff --git a/JavaToCSharp/Declarations/AnnotationDeclarationVisitor.cs b/JavaToCSharp/Declarations/AnnotationDeclarationVisitor.cs index 493a490c..dfe52342 100644 --- a/JavaToCSharp/Declarations/AnnotationDeclarationVisitor.cs +++ b/JavaToCSharp/Declarations/AnnotationDeclarationVisitor.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using com.github.javaparser; +using com.github.javaparser; using com.github.javaparser.ast.body; using com.github.javaparser.ast.type; using Microsoft.CodeAnalysis.CSharp.Syntax; diff --git a/JavaToCSharp/Declarations/BodyDeclarationVisitor.cs b/JavaToCSharp/Declarations/BodyDeclarationVisitor.cs index c5d7a382..a840de3b 100644 --- a/JavaToCSharp/Declarations/BodyDeclarationVisitor.cs +++ b/JavaToCSharp/Declarations/BodyDeclarationVisitor.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using com.github.javaparser.ast.body; +using com.github.javaparser.ast.body; using com.github.javaparser.ast.type; using Microsoft.CodeAnalysis.CSharp.Syntax; using Range = com.github.javaparser.Range; diff --git a/JavaToCSharp/Declarations/ClassOrInterfaceDeclarationVisitor.cs b/JavaToCSharp/Declarations/ClassOrInterfaceDeclarationVisitor.cs index 23494ebe..fe18368d 100644 --- a/JavaToCSharp/Declarations/ClassOrInterfaceDeclarationVisitor.cs +++ b/JavaToCSharp/Declarations/ClassOrInterfaceDeclarationVisitor.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using System.Linq; -using com.github.javaparser.ast; +using com.github.javaparser.ast; using com.github.javaparser.ast.body; using com.github.javaparser.ast.expr; using com.github.javaparser.ast.type; @@ -71,7 +69,7 @@ public static InterfaceDeclarationSyntax VisitInterfaceDeclaration(ConversionCon var extends = interfaceDecl.getExtendedTypes().ToList(); - if (extends != null) + if (extends is not null) { foreach (var extend in extends) { @@ -81,7 +79,7 @@ public static InterfaceDeclarationSyntax VisitInterfaceDeclaration(ConversionCon var implements = interfaceDecl.getImplementedTypes().ToList(); - if (implements != null) + if (implements is not null) { foreach (var implement in implements) { @@ -98,7 +96,7 @@ public static InterfaceDeclarationSyntax VisitInterfaceDeclaration(ConversionCon var syntax = VisitBodyDeclarationForInterface(context, classSyntax, member); var memberWithComments = syntax?.WithJavaComments(context, member); - if (memberWithComments != null) + if (memberWithComments is not null) { classSyntax = classSyntax.AddMembers(memberWithComments); } @@ -144,14 +142,14 @@ public static ClassDeclarationSyntax VisitClassDeclaration(ConversionContext con if (mods.Contains(Modifier.Keyword.FINAL)) classSyntax = classSyntax.AddModifiers(SyntaxFactory.Token(SyntaxKind.SealedKeyword)); - var extends = classDecl.getExtendedTypes().ToList() ?? new List(); + var extends = classDecl.getExtendedTypes().ToList() ?? []; foreach (var extend in extends) { classSyntax = classSyntax.AddBaseListTypes(SyntaxFactory.SimpleBaseType(TypeHelper.GetSyntaxFromType(extend))); } - var implements = classDecl.getImplementedTypes().ToList() ?? new List(); + var implements = classDecl.getImplementedTypes().ToList() ?? []; foreach (var implement in implements) { @@ -184,7 +182,7 @@ public static ClassDeclarationSyntax VisitClassDeclaration(ConversionContext con var syntax = VisitBodyDeclarationForClass(context, classSyntax, member, extends, implements); var withJavaComments = syntax?.WithJavaComments(context, member); - if (withJavaComments != null) + if (withJavaComments is not null) { classSyntax = classSyntax.AddMembers(withJavaComments); } diff --git a/JavaToCSharp/Declarations/ConstructorDeclarationVisitor.cs b/JavaToCSharp/Declarations/ConstructorDeclarationVisitor.cs index 39b28fb3..5566c8f6 100644 --- a/JavaToCSharp/Declarations/ConstructorDeclarationVisitor.cs +++ b/JavaToCSharp/Declarations/ConstructorDeclarationVisitor.cs @@ -72,7 +72,7 @@ public class ConstructorDeclarationVisitor : BodyDeclarationVisitor 0) + if (initArgs is not null && initArgs.size() > 0) { argsSyntax = TypeHelper.GetSyntaxFromArguments(context, initArgs); } diff --git a/JavaToCSharp/Declarations/EnumDeclarationVisitor.cs b/JavaToCSharp/Declarations/EnumDeclarationVisitor.cs index 16a34302..97a700cc 100644 --- a/JavaToCSharp/Declarations/EnumDeclarationVisitor.cs +++ b/JavaToCSharp/Declarations/EnumDeclarationVisitor.cs @@ -56,7 +56,7 @@ public static EnumDeclarationSyntax VisitEnumDeclaration(ConversionContext conte var classBody = itemConst.getClassBody(); if (!constArgs.isEmpty() || !classBody.isEmpty()) { - var bodyCodes = CommentsHelper.ConvertToComment(new[] { itemConst }, "enum member body", false); + var bodyCodes = CommentsHelper.ConvertToComment([itemConst], "enum member body", false); if (memberDecl.HasLeadingTrivia) { diff --git a/JavaToCSharp/Declarations/FieldDeclarationVisitor.cs b/JavaToCSharp/Declarations/FieldDeclarationVisitor.cs index 78e3a5fc..d37cc9ed 100644 --- a/JavaToCSharp/Declarations/FieldDeclarationVisitor.cs +++ b/JavaToCSharp/Declarations/FieldDeclarationVisitor.cs @@ -47,7 +47,7 @@ public override MemberDeclarationSyntax VisitForClass( var initExpr = item.getInitializer().FromOptional(); - if (initExpr != null) + if (initExpr is not null) { var initSyntax = ExpressionVisitor.VisitExpression(context, initExpr); diff --git a/JavaToCSharp/Declarations/InitializerDeclarationVisitor.cs b/JavaToCSharp/Declarations/InitializerDeclarationVisitor.cs index 99f4f115..1cbb03f8 100644 --- a/JavaToCSharp/Declarations/InitializerDeclarationVisitor.cs +++ b/JavaToCSharp/Declarations/InitializerDeclarationVisitor.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using com.github.javaparser; +using com.github.javaparser; using com.github.javaparser.ast.body; using com.github.javaparser.ast.type; using JavaToCSharp.Statements; diff --git a/JavaToCSharp/Declarations/MethodDeclarationVisitor.cs b/JavaToCSharp/Declarations/MethodDeclarationVisitor.cs index d4b489f8..645757a2 100644 --- a/JavaToCSharp/Declarations/MethodDeclarationVisitor.cs +++ b/JavaToCSharp/Declarations/MethodDeclarationVisitor.cs @@ -55,7 +55,7 @@ public override MemberDeclarationSyntax VisitForInterface(ConversionContext cont { var paramSyntax = parameters.Select(i => SyntaxFactory.Parameter( - attributeLists: new SyntaxList(), + attributeLists: [], modifiers: SyntaxFactory.TokenList(), type: SyntaxFactory.ParseTypeName(TypeHelper.ConvertTypeOf(i)), identifier: SyntaxFactory.ParseToken(TypeHelper.EscapeIdentifier(i.getNameAsString())), @@ -110,7 +110,7 @@ private static MemberDeclarationSyntax VisitInternal( bool isOverride = false; // TODO: figure out how to check for a non-interface base type - if (annotations is {Count: > 0}) + if (annotations is { Count: > 0 }) { foreach (var annotation in annotations) { @@ -124,7 +124,7 @@ private static MemberDeclarationSyntax VisitInternal( isOverride = true; } // add annotation if a mapping is found - else if (context.Options != null && context.Options.SyntaxMappings.AnnotationMappings.TryGetValue(name, out var mappedAnnotation)) + else if (context.Options is not null && context.Options.SyntaxMappings.AnnotationMappings.TryGetValue(name, out var mappedAnnotation)) { var attributeList = SyntaxFactory.AttributeList( SyntaxFactory.SingletonSeparatedList( @@ -180,7 +180,7 @@ private static MemberDeclarationSyntax VisitInternal( var block = methodDecl.getBody().FromOptional(); - if (block == null) + if (block is null) { // i.e. abstract method methodSyntax = methodSyntax.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); @@ -196,20 +196,11 @@ private static MemberDeclarationSyntax VisitInternal( { var lockBlock = SyntaxFactory.Block(statementSyntax); - LockStatementSyntax? lockSyntax = null; - if (mods.Contains(Modifier.Keyword.STATIC)) - { - lockSyntax = SyntaxFactory.LockStatement(SyntaxFactory.TypeOfExpression(SyntaxFactory.ParseTypeName(typeIdentifier)), lockBlock); - } - else - { - lockSyntax = SyntaxFactory.LockStatement(SyntaxFactory.ThisExpression(), lockBlock); - } + var lockSyntax = mods.Contains(Modifier.Keyword.STATIC) + ? SyntaxFactory.LockStatement(SyntaxFactory.TypeOfExpression(SyntaxFactory.ParseTypeName(typeIdentifier)), lockBlock) + : SyntaxFactory.LockStatement(SyntaxFactory.ThisExpression(), lockBlock); - if (lockSyntax is not null) - { - methodSyntax = methodSyntax.AddBodyStatements(lockSyntax); - } + methodSyntax = methodSyntax.AddBodyStatements(lockSyntax); } else { diff --git a/JavaToCSharp/Expressions/ArrayAccessExpressionVisitor.cs b/JavaToCSharp/Expressions/ArrayAccessExpressionVisitor.cs index d2bf676d..3c16710e 100644 --- a/JavaToCSharp/Expressions/ArrayAccessExpressionVisitor.cs +++ b/JavaToCSharp/Expressions/ArrayAccessExpressionVisitor.cs @@ -22,9 +22,9 @@ public class ArrayAccessExpressionVisitor : ExpressionVisitor return null; } - return SyntaxFactory.ElementAccessExpression(nameSyntax, SyntaxFactory.BracketedArgumentList(SyntaxFactory.SeparatedList(new[] - { + return SyntaxFactory.ElementAccessExpression(nameSyntax, SyntaxFactory.BracketedArgumentList(SyntaxFactory.SeparatedList( + [ SyntaxFactory.Argument(indexSyntax) - }))); + ]))); } } diff --git a/JavaToCSharp/Expressions/ArrayCreationExpressionVisitor.cs b/JavaToCSharp/Expressions/ArrayCreationExpressionVisitor.cs index 4f8d62c6..89f9d4f8 100644 --- a/JavaToCSharp/Expressions/ArrayCreationExpressionVisitor.cs +++ b/JavaToCSharp/Expressions/ArrayCreationExpressionVisitor.cs @@ -26,30 +26,34 @@ protected override ExpressionSyntax Visit(ConversionContext context, ArrayCreati var rankSyntaxes = new List(); - if (rankDimensions != null) + if (rankDimensions is not null) { - var expressionSyntaxes = rankDimensions.Select(dimension => - VisitExpression(context, dimension.getDimension().FromOptional())) - .Where(syntax => syntax != null); - rankSyntaxes.AddRange(expressionSyntaxes!); + var expressionSyntaxes = rankDimensions + .Select(dimension => VisitExpression(context, dimension.getDimension().FromOptional())) + .OfType(); // filter out nulls + rankSyntaxes.AddRange(expressionSyntaxes); } var rankSpecifier = rankDimensions?.Count > 0 && rankSyntaxes.Count == 0 ? SyntaxFactory.ArrayRankSpecifier(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.OmittedArraySizeExpression())) : SyntaxFactory.ArrayRankSpecifier(SyntaxFactory.SeparatedList(rankSyntaxes, Enumerable.Repeat(SyntaxFactory.Token(SyntaxKind.CommaToken), rankSyntaxes.Count - 1))); - if (initializer == null) + if (initializer is null) + { return SyntaxFactory.ArrayCreationExpression(arrayTypeSyntax) .AddTypeRankSpecifiers(rankSpecifier); + } // todo: support multi-dimensional and jagged arrays - var values = initializer.getValues()?.ToList() ?? new List(); + var values = initializer.getValues()?.ToList() ?? []; + var syntaxes = values.Select(value => VisitExpression(context, value)) - .Where(syntax => syntax != null)! - .ToList(); + .OfType() // filter out nulls + .ToList(); + var initSyntax = - syntaxes.Any() + syntaxes.Count != 0 ? SyntaxFactory.InitializerExpression(SyntaxKind.ArrayInitializerExpression, SyntaxFactory.SeparatedList(syntaxes, Enumerable.Repeat(SyntaxFactory.Token(SyntaxKind.CommaToken), syntaxes.Count - 1))) diff --git a/JavaToCSharp/Expressions/ArrayInitializerExpressionVisitor.cs b/JavaToCSharp/Expressions/ArrayInitializerExpressionVisitor.cs index 667d8a01..31e575b7 100644 --- a/JavaToCSharp/Expressions/ArrayInitializerExpressionVisitor.cs +++ b/JavaToCSharp/Expressions/ArrayInitializerExpressionVisitor.cs @@ -8,10 +8,10 @@ public class ArrayInitializerExpressionVisitor : ExpressionVisitor() ?? new List(); + var expressions = expr.getValues()?.ToList() ?? []; var syntaxes = expressions.Select(valueExpression => VisitExpression(context, valueExpression)) - .Where(syntax => syntax != null)! - .ToList(); + .OfType() // filter out nulls + .ToList(); return SyntaxFactory.ImplicitArrayCreationExpression( SyntaxFactory.InitializerExpression( diff --git a/JavaToCSharp/Expressions/ExpressionVisitor.cs b/JavaToCSharp/Expressions/ExpressionVisitor.cs index 51d67a09..0f26be13 100644 --- a/JavaToCSharp/Expressions/ExpressionVisitor.cs +++ b/JavaToCSharp/Expressions/ExpressionVisitor.cs @@ -55,7 +55,7 @@ static ExpressionVisitor() public static ExpressionSyntax? VisitExpression(ConversionContext context, Expression? expr) { - if (expr == null) + if (expr is null) { return null; } @@ -63,12 +63,12 @@ static ExpressionVisitor() ExpressionVisitor? visitor = null; var t = expr.GetType(); - while (t != null && !_visitors.TryGetValue(t, out visitor)) + while (t is not null && !_visitors.TryGetValue(t, out visitor)) { t = t.BaseType; } - if (visitor != null) + if (visitor is not null) { return visitor.Visit(context, expr); } diff --git a/JavaToCSharp/Expressions/FieldAccessExpressionVisitor.cs b/JavaToCSharp/Expressions/FieldAccessExpressionVisitor.cs index 4d7bc601..69ef55ec 100644 --- a/JavaToCSharp/Expressions/FieldAccessExpressionVisitor.cs +++ b/JavaToCSharp/Expressions/FieldAccessExpressionVisitor.cs @@ -11,7 +11,7 @@ public class FieldAccessExpressionVisitor : ExpressionVisitor var scope = fieldAccessExpr.getScope(); ExpressionSyntax? scopeSyntax = null; - if (scope != null) + if (scope is not null) { scopeSyntax = VisitExpression(context, scope); diff --git a/JavaToCSharp/Expressions/MethodCallExpressionVisitor.cs b/JavaToCSharp/Expressions/MethodCallExpressionVisitor.cs index d50a5c3f..2bc27069 100644 --- a/JavaToCSharp/Expressions/MethodCallExpressionVisitor.cs +++ b/JavaToCSharp/Expressions/MethodCallExpressionVisitor.cs @@ -19,7 +19,7 @@ public class MethodCallExpressionVisitor : ExpressionVisitor var methodName = TypeHelper.Capitalize(methodCallExpr.getNameAsString()); methodName = TypeHelper.ReplaceCommonMethodNames(methodName); - if (scope != null) + if (scope is not null) { scopeSyntax = VisitExpression(context, scope); @@ -49,7 +49,7 @@ public class MethodCallExpressionVisitor : ExpressionVisitor ExpressionSyntax methodExpression; - if (scopeSyntax == null) + if (scopeSyntax is null) { methodExpression = SyntaxFactory.IdentifierName(methodName); } @@ -60,7 +60,7 @@ public class MethodCallExpressionVisitor : ExpressionVisitor var args = methodCallExpr.getArguments(); - if (args == null || args.size() == 0) + if (args is null || args.size() == 0) { return SyntaxFactory.InvocationExpression(methodExpression); } @@ -71,12 +71,12 @@ public class MethodCallExpressionVisitor : ExpressionVisitor private static bool TryGetMappedMethodName(string methodName, Expression? scope, ConversionContext context, out string mappedMethodName) { var mappings = context.Options.SyntaxMappings; - if (scope == null && mappings.VoidMethodMappings.TryGetValue(methodName, out var voidMapping)) + if (scope is null && mappings.VoidMethodMappings.TryGetValue(methodName, out var voidMapping)) { mappedMethodName = voidMapping; return true; } - else if (scope != null && mappings.NonVoidMethodMappings.TryGetValue(methodName, out var nonVoidMapping)) + else if (scope is not null && mappings.NonVoidMethodMappings.TryGetValue(methodName, out var nonVoidMapping)) { mappedMethodName = nonVoidMapping; return true; diff --git a/JavaToCSharp/Expressions/MethodReferenceExpressionVisitor.cs b/JavaToCSharp/Expressions/MethodReferenceExpressionVisitor.cs index bf980604..27af830a 100644 --- a/JavaToCSharp/Expressions/MethodReferenceExpressionVisitor.cs +++ b/JavaToCSharp/Expressions/MethodReferenceExpressionVisitor.cs @@ -12,7 +12,7 @@ protected override ExpressionSyntax Visit(ConversionContext context, MethodRefer var scope = expr.getScope(); ExpressionSyntax? scopeSyntax = null; - if (scope != null) + if (scope is not null) { scopeSyntax = VisitExpression(context, scope); } @@ -22,7 +22,7 @@ protected override ExpressionSyntax Visit(ConversionContext context, MethodRefer ExpressionSyntax methodExpression; - if (scopeSyntax == null) + if (scopeSyntax is null) { methodExpression = SyntaxFactory.IdentifierName(methodName); } @@ -33,7 +33,7 @@ protected override ExpressionSyntax Visit(ConversionContext context, MethodRefer var args = expr.getTypeArguments().FromOptional(); - if (args == null || args.size() == 0) + if (args is null || args.size() == 0) { return SyntaxFactory.InvocationExpression(methodExpression); } diff --git a/JavaToCSharp/Expressions/ObjectCreationExpressionVisitor.cs b/JavaToCSharp/Expressions/ObjectCreationExpressionVisitor.cs index a77708dd..c972d063 100644 --- a/JavaToCSharp/Expressions/ObjectCreationExpressionVisitor.cs +++ b/JavaToCSharp/Expressions/ObjectCreationExpressionVisitor.cs @@ -14,7 +14,7 @@ protected override ExpressionSyntax Visit(ConversionContext context, ObjectCreat { var anonBody = newExpr.getAnonymousClassBody().FromOptional().ToList(); - if (anonBody is {Count: > 0}) + if (anonBody is { Count: > 0 }) { return VisitAnonymousClassCreationExpression(context, newExpr, anonBody); } @@ -23,7 +23,7 @@ protected override ExpressionSyntax Visit(ConversionContext context, ObjectCreat //var scope = newExpr.getScope(); //ExpressionSyntax scopeSyntax = null; - //if (scope != null) { + //if (scope is not null) { // scopeSyntax = ExpressionVisitor.VisitExpression(context, scope); //} @@ -33,7 +33,7 @@ protected override ExpressionSyntax Visit(ConversionContext context, ObjectCreat var args = newExpr.getArguments(); - if (args == null || args.size() == 0) + if (args is null || args.size() == 0) { return SyntaxFactory.ObjectCreationExpression(typeSyntax).WithArgumentList(SyntaxFactory.ArgumentList()); } @@ -89,16 +89,16 @@ private static ObjectCreationExpressionSyntax VisitAnonymousClassCreationExpress // TODO.PI: do we need to pass extends/implements here? foreach (var memberSyntax in anonBody .Select(member => BodyDeclarationVisitor.VisitBodyDeclarationForClass(context, classSyntax, member, new List(), new List())) - .Where(memberSyntax => memberSyntax != null)) + .OfType()) { - classSyntax = classSyntax.AddMembers(memberSyntax!); + classSyntax = classSyntax.AddMembers(memberSyntax); } context.PendingAnonymousTypes.Enqueue(classSyntax); var args = newExpr.getArguments(); - if (args == null || args.size() == 0) + if (args is null || args.size() == 0) { return SyntaxFactory.ObjectCreationExpression(SyntaxFactory.ParseTypeName(anonTypeName)) .AddArgumentListArguments(SyntaxFactory.Argument(SyntaxFactory.ThisExpression())); diff --git a/JavaToCSharp/Extensions.cs b/JavaToCSharp/Extensions.cs index 8d959606..dcaa31dc 100644 --- a/JavaToCSharp/Extensions.cs +++ b/JavaToCSharp/Extensions.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using java.util; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using JavaAst = com.github.javaparser.ast; @@ -9,81 +8,98 @@ namespace JavaToCSharp; public static class Extensions { - /// - /// Converts a Java Iterable to a .NET IEnumerable<T> and filters the elements of type T. - /// - /// Type of items to be returned. /// The java Iterable to be enumerated. - /// A filtered enumeration of items of type T - public static IEnumerable OfType(this java.lang.Iterable iterable) + extension(java.lang.Iterable iterable) { - var iterator = iterable.iterator(); - while (iterator.hasNext()) + /// + /// Converts a Java Iterable to a .NET IEnumerable<T> and filters the elements of type T. + /// + /// Type of items to be returned. + /// A filtered enumeration of items of type T + public IEnumerable OfType() { - if (iterator.next() is T item) + var iterator = iterable.iterator(); + while (iterator.hasNext()) { - yield return item; + if (iterator.next() is T item) + { + yield return item; + } } } } - public static List? ToList(this java.util.List? list) + extension(java.util.List? list) { - if (list == null) - return null; + public List? ToList() + { + if (list is null) + { + return null; + } - var newList = new List(); + var newList = new List(); - for (int i = 0; i < list.size(); i++) - { - newList.Add((T)list.get(i)); - } + for (int i = 0; i < list.size(); i++) + { + newList.Add((T)list.get(i)); + } - return newList; + return newList; + } } - public static bool HasFlag(this java.util.EnumSet values, T flag) => values.contains(flag); - - [return: NotNullIfNotNull(nameof(node))] - public static TSyntax? WithJavaComments(this TSyntax? syntax, - ConversionContext context, - JavaAst.Node? node) - where TSyntax : SyntaxNode - => context.Options.IncludeComments - ? CommentsHelper.AddCommentsTrivias(syntax, node) - : syntax; + extension(java.util.EnumSet values) + { + public bool HasFlag(T flag) => values.contains(flag); + } - public static CompilationUnitSyntax WithPackageFileComments(this CompilationUnitSyntax syntax, - ConversionContext context, + extension(CompilationUnitSyntax syntax) + { + public CompilationUnitSyntax WithPackageFileComments(ConversionContext context, JavaAst.CompilationUnit compilationUnit, JavaAst.PackageDeclaration? packageDeclaration) - => context.Options.IncludeComments - ? CommentsHelper.AddPackageComments(syntax, compilationUnit, packageDeclaration) - : syntax; + => context.Options.IncludeComments + ? CommentsHelper.AddPackageComments(syntax, compilationUnit, packageDeclaration) + : syntax; + } - public static T? FromOptional(this Optional optional) - where T : class - => optional.isPresent() - ? optional.get() as T ?? - throw new InvalidOperationException($"Optional did not convert to {typeof(T)}") - : null; + extension(Optional optional) + { + public T? FromOptional() + where T : class + => optional.isPresent() + ? optional.get() as T ?? throw new InvalidOperationException($"Optional did not convert to {typeof(T)}") + : null; - public static T FromRequiredOptional(this Optional optional) - where T : class - => optional.isPresent() - ? optional.get() as T ?? - throw new InvalidOperationException($"Optional did not convert to {typeof(T)}") - : throw new InvalidOperationException("Required optional did not have a value"); + public T FromRequiredOptional() + where T : class + => optional.isPresent() + ? optional.get() as T ?? throw new InvalidOperationException($"Optional did not convert to {typeof(T)}") + : throw new InvalidOperationException("Required optional did not have a value"); + } - public static ISet ToModifierKeywordSet(this JavaAst.NodeList nodeList) - => nodeList.ToList()?.Select(i => i.getKeyword()).ToHashSet() - ?? new HashSet(); + extension(JavaAst.NodeList nodeList) + { + public ISet ToModifierKeywordSet() + => nodeList.ToList()?.Select(i => i.getKeyword()).ToHashSet() ?? []; + } - public static TSyntax WithLeadingNewLines(this TSyntax syntax, int count = 1) - where TSyntax : SyntaxNode - => syntax.WithLeadingTrivia(Enumerable.Repeat(Whitespace.NewLine, count)); + extension(TSyntax syntax) where TSyntax : SyntaxNode + { + public TSyntax WithLeadingNewLines(int count = 1) + => syntax.WithLeadingTrivia(Enumerable.Repeat(Whitespace.NewLine, count)); + + public TSyntax WithTrailingNewLines(int count = 1) + => syntax.WithTrailingTrivia(Enumerable.Repeat(Whitespace.NewLine, count)); + } - public static TSyntax WithTrailingNewLines(this TSyntax syntax, int count = 1) - where TSyntax : SyntaxNode - => syntax.WithTrailingTrivia(Enumerable.Repeat(Whitespace.NewLine, count)); + extension(TSyntax? syntax) where TSyntax : SyntaxNode + { + [return: NotNullIfNotNull(nameof(node))] + public TSyntax? WithJavaComments(ConversionContext context, JavaAst.Node? node) + => context.Options.IncludeComments + ? CommentsHelper.AddCommentsTrivias(syntax, node) + : syntax; + } } diff --git a/JavaToCSharp/JavaToCSharp.csproj b/JavaToCSharp/JavaToCSharp.csproj index 66903f14..2cad3e2c 100644 --- a/JavaToCSharp/JavaToCSharp.csproj +++ b/JavaToCSharp/JavaToCSharp.csproj @@ -1,27 +1,28 @@  - - 4.0.0 - net10.0 - enable - enable - nullable - Paul Irwin - A Java to C# converter. - Copyright 2021-2023, Paul Irwin - MIT - https://github.com/paulirwin/JavaToCSharp - latest - - - - - - - - - - - - - + + 4.0.0 + net10.0 + enable + enable + true + Paul Irwin + A Java to C# converter. + Copyright 2021-2025, Paul Irwin + MIT + https://github.com/paulirwin/JavaToCSharp + latest + + + + + + + + + + + + + + diff --git a/JavaToCSharp/JavaToCSharpConverter.cs b/JavaToCSharp/JavaToCSharpConverter.cs index 3d11362e..676dbacf 100644 --- a/JavaToCSharp/JavaToCSharpConverter.cs +++ b/JavaToCSharp/JavaToCSharpConverter.cs @@ -49,8 +49,8 @@ public static class JavaToCSharpConverter options.ConversionStateChanged(ConversionState.BuildingCSharpAst); - var types = result.getTypes().ToList() ?? new List(); - var imports = result.getImports()?.ToList() ?? new List(); + var types = result.getTypes().ToList() ?? []; + var imports = result.getImports()?.ToList() ?? []; var package = result.getPackageDeclaration().FromOptional(); var rootMembers = new List(); @@ -67,7 +67,7 @@ public static class JavaToCSharpConverter continue; } - packageName = packageReplacement.Replace(packageName)!; + packageName = packageReplacement.Replace(packageName); } packageName = TypeHelper.Capitalize(packageName); @@ -105,7 +105,7 @@ public static class JavaToCSharpConverter } } - if (namespaceNameSyntax != null) + if (namespaceNameSyntax is not null) { if (options.UseFileScopedNamespaces && rootMembers.Count > 0) { diff --git a/JavaToCSharp/Replacement.cs b/JavaToCSharp/Replacement.cs index 18874428..00213b9e 100644 --- a/JavaToCSharp/Replacement.cs +++ b/JavaToCSharp/Replacement.cs @@ -2,24 +2,19 @@ namespace JavaToCSharp; -public class Replacement +public class Replacement(string pattern, string replacement, RegexOptions options = RegexOptions.None) { - public Replacement(string pattern, string replacement, RegexOptions options = RegexOptions.None) - { - Regex = new Regex(pattern, options); - ReplacementValue = replacement; - } + public Regex Regex { get; } = new(pattern, options); - public Regex? Regex { get; } + public string? ReplacementValue { get; } = replacement; - public string? ReplacementValue { get; } - - public string? Replace(string input) => string.IsNullOrWhiteSpace(ReplacementValue) ? null : Regex?.Replace(input, ReplacementValue); + public string Replace(string input) + => string.IsNullOrWhiteSpace(ReplacementValue) + ? string.Empty + : Regex.Replace(input, ReplacementValue); protected bool Equals(Replacement other) - { - return Equals(Regex, other.Regex) && ReplacementValue == other.ReplacementValue; - } + => Equals(Regex, other.Regex) && ReplacementValue == other.ReplacementValue; public override bool Equals(object? obj) { @@ -30,10 +25,5 @@ public override bool Equals(object? obj) } public override int GetHashCode() - { - unchecked - { - return ((Regex != null ? Regex.GetHashCode() : 0) * 397) ^ (ReplacementValue != null ? ReplacementValue.GetHashCode() : 0); - } - } + => HashCode.Combine(Regex, ReplacementValue); } diff --git a/JavaToCSharp/SanitizingSyntaxRewriter.cs b/JavaToCSharp/SanitizingSyntaxRewriter.cs index 37a1689f..d6b910f9 100644 --- a/JavaToCSharp/SanitizingSyntaxRewriter.cs +++ b/JavaToCSharp/SanitizingSyntaxRewriter.cs @@ -11,7 +11,7 @@ internal class SanitizingSyntaxRewriter : CSharpSyntaxRewriter { public override SyntaxNode? Visit(SyntaxNode? node) { - if (node != null) + if (node is not null) { // We must do this after whitespace normalization! node = CommentsHelper.FixCommentsWhitespaces(node); diff --git a/JavaToCSharp/Statements/AssertStatementVisitor.cs b/JavaToCSharp/Statements/AssertStatementVisitor.cs index b7c9b2cf..50cac058 100644 --- a/JavaToCSharp/Statements/AssertStatementVisitor.cs +++ b/JavaToCSharp/Statements/AssertStatementVisitor.cs @@ -11,7 +11,9 @@ public class AssertStatementVisitor : StatementVisitor public override StatementSyntax? Visit(ConversionContext context, AssertStmt assertStmt) { if (!context.Options.UseDebugAssertForAsserts) + { return null; + } var check = assertStmt.getCheck(); var checkSyntax = ExpressionVisitor.VisitExpression(context, check); @@ -22,14 +24,15 @@ public class AssertStatementVisitor : StatementVisitor var message = assertStmt.getMessage().FromOptional(); - if (message == null) + if (message is null) + { return SyntaxFactory.ExpressionStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.IdentifierName("Debug.Assert"), - SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[] - { + SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList([ SyntaxFactory.Argument(checkSyntax) - })))); + ])))); + } var messageSyntax = ExpressionVisitor.VisitExpression(context, message); if (messageSyntax is null) @@ -40,6 +43,7 @@ public class AssertStatementVisitor : StatementVisitor return SyntaxFactory.ExpressionStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.IdentifierName("Debug.Assert"), - SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.Argument(checkSyntax), SyntaxFactory.Argument(messageSyntax) }, new[] { SyntaxFactory.Token(SyntaxKind.CommaToken) })))); + SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList([SyntaxFactory.Argument(checkSyntax), SyntaxFactory.Argument(messageSyntax) + ], [SyntaxFactory.Token(SyntaxKind.CommaToken)])))); } } diff --git a/JavaToCSharp/Statements/ExpressionStatementVisitor.cs b/JavaToCSharp/Statements/ExpressionStatementVisitor.cs index 2300f6b1..262cdbc7 100644 --- a/JavaToCSharp/Statements/ExpressionStatementVisitor.cs +++ b/JavaToCSharp/Statements/ExpressionStatementVisitor.cs @@ -15,7 +15,9 @@ public class ExpressionStatementVisitor : StatementVisitor // handle special case where AST is different if (expression is VariableDeclarationExpr expr) + { return VisitVariableDeclarationStatement(context, expr); + } var expressionSyntax = ExpressionVisitor.VisitExpression(context, expression); @@ -55,7 +57,7 @@ private static StatementSyntax VisitVariableDeclarationStatement(ConversionConte var initExpr = item.getInitializer().FromOptional(); - if (initExpr != null) + if (initExpr is not null) { var initSyntax = ExpressionVisitor.VisitExpression(context, initExpr); if (initSyntax is not null) @@ -65,7 +67,9 @@ private static StatementSyntax VisitVariableDeclarationStatement(ConversionConte } } else + { variables.Add(SyntaxFactory.VariableDeclarator(name)); + } } var typeSyntax = TypeHelper.ConvertTypeSyntax(commonType, arrayRank ?? 0); diff --git a/JavaToCSharp/Statements/ForEachStatementVisitor.cs b/JavaToCSharp/Statements/ForEachStatementVisitor.cs index f2b54250..19a43bec 100644 --- a/JavaToCSharp/Statements/ForEachStatementVisitor.cs +++ b/JavaToCSharp/Statements/ForEachStatementVisitor.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using System.Linq; -using com.github.javaparser.ast.body; +using com.github.javaparser.ast.body; using com.github.javaparser.ast.stmt; using JavaToCSharp.Expressions; using Microsoft.CodeAnalysis.CSharp; @@ -23,7 +21,7 @@ public class ForEachStatementVisitor : StatementVisitor var varType = varExpr.getCommonType(); var type = TypeHelper.ConvertType(varType); - var variableDeclarators = varExpr.getVariables()?.ToList()?? new List(); + var variableDeclarators = varExpr.getVariables()?.ToList()?? []; var vars = variableDeclarators .Select(i => SyntaxFactory.VariableDeclarator(i.toString())) .ToArray(); @@ -31,6 +29,6 @@ public class ForEachStatementVisitor : StatementVisitor var body = foreachStmt.getBody(); var bodySyntax = VisitStatement(context, body); - return bodySyntax == null ? null : SyntaxFactory.ForEachStatement(SyntaxFactory.ParseTypeName(type), vars[0].Identifier.ValueText, iterableSyntax, bodySyntax); + return bodySyntax is null ? null : SyntaxFactory.ForEachStatement(SyntaxFactory.ParseTypeName(type), vars[0].Identifier.ValueText, iterableSyntax, bodySyntax); } } diff --git a/JavaToCSharp/Statements/ForStatementVisitor.cs b/JavaToCSharp/Statements/ForStatementVisitor.cs index 33ca65c8..1f20c533 100644 --- a/JavaToCSharp/Statements/ForStatementVisitor.cs +++ b/JavaToCSharp/Statements/ForStatementVisitor.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using System.Linq; -using com.github.javaparser.ast.body; +using com.github.javaparser.ast.body; using com.github.javaparser.ast.expr; using com.github.javaparser.ast.stmt; using JavaToCSharp.Expressions; @@ -18,7 +16,7 @@ public class ForStatementVisitor : StatementVisitor var initSyntaxes = new List(); VariableDeclarationSyntax? varSyntax = null; - if (inits != null) + if (inits is not null) { foreach (var init in inits) { @@ -26,7 +24,7 @@ public class ForStatementVisitor : StatementVisitor { var type = TypeHelper.ConvertType(varExpr.getCommonType()); - var variableDeclarators = varExpr.getVariables()?.ToList() ?? new List(); + var variableDeclarators = varExpr.getVariables()?.ToList() ?? []; var vars = variableDeclarators .Select(i => SyntaxFactory.VariableDeclarator(i.toString())) .ToArray(); @@ -50,17 +48,19 @@ public class ForStatementVisitor : StatementVisitor var increments = forStmt.getUpdate().ToList(); var incrementSyntaxes = new List(); - if (increments != null) + if (increments is not null) { var expressionSyntaxes = increments.Select(increment => ExpressionVisitor.VisitExpression(context, increment)); - incrementSyntaxes.AddRange(expressionSyntaxes.Where(expressionSyntax => expressionSyntax != null)!); + incrementSyntaxes.AddRange(expressionSyntaxes.OfType()); } var body = forStmt.getBody(); var bodySyntax = VisitStatement(context, body); - if (bodySyntax == null) + if (bodySyntax is null) + { return null; + } return SyntaxFactory.ForStatement(bodySyntax) .WithDeclaration(varSyntax) diff --git a/JavaToCSharp/Statements/IfStatementVisitor.cs b/JavaToCSharp/Statements/IfStatementVisitor.cs index f50f210c..1f5f8f67 100644 --- a/JavaToCSharp/Statements/IfStatementVisitor.cs +++ b/JavaToCSharp/Statements/IfStatementVisitor.cs @@ -11,6 +11,7 @@ public class IfStatementVisitor : StatementVisitor { var condition = ifStmt.getCondition(); var conditionSyntax = ExpressionVisitor.VisitExpression(context, condition); + if (conditionSyntax is null) { return null; @@ -19,20 +20,25 @@ public class IfStatementVisitor : StatementVisitor var thenStmt = ifStmt.getThenStmt(); var thenSyntax = VisitStatement(context, thenStmt); - if (thenSyntax == null) + if (thenSyntax is null) + { return null; + } var elseStmt = ifStmt.getElseStmt().FromOptional(); - if (elseStmt == null) + if (elseStmt is null) + { return SyntaxFactory.IfStatement(conditionSyntax, thenSyntax); + } var elseStatementSyntax = VisitStatement(context, elseStmt); + if (elseStatementSyntax is null) { return null; } - + var elseSyntax = SyntaxFactory.ElseClause(elseStatementSyntax); return SyntaxFactory.IfStatement(conditionSyntax, thenSyntax, elseSyntax); } diff --git a/JavaToCSharp/Statements/LabeledStatementVisitor.cs b/JavaToCSharp/Statements/LabeledStatementVisitor.cs index 7a5958c5..dbba5333 100644 --- a/JavaToCSharp/Statements/LabeledStatementVisitor.cs +++ b/JavaToCSharp/Statements/LabeledStatementVisitor.cs @@ -11,6 +11,6 @@ public class LabeledStatementVisitor : StatementVisitor var statement = labeledStmt.getStatement(); var syntax = VisitStatement(context, statement); - return syntax == null ? null : SyntaxFactory.LabeledStatement(labeledStmt.getLabel().asString(), syntax); + return syntax is null ? null : SyntaxFactory.LabeledStatement(labeledStmt.getLabel().asString(), syntax); } -} \ No newline at end of file +} diff --git a/JavaToCSharp/Statements/ReturnStatementVisitor.cs b/JavaToCSharp/Statements/ReturnStatementVisitor.cs index d3542523..3b92de16 100644 --- a/JavaToCSharp/Statements/ReturnStatementVisitor.cs +++ b/JavaToCSharp/Statements/ReturnStatementVisitor.cs @@ -12,8 +12,10 @@ public override StatementSyntax Visit(ConversionContext context, ReturnStmt retu { var expr = returnStmt.getExpression().FromOptional(); - if (expr == null) + if (expr is null) + { return SyntaxFactory.ReturnStatement(); // i.e. "return" in a void method + } var exprSyntax = ExpressionVisitor.VisitExpression(context, expr); diff --git a/JavaToCSharp/Statements/StatementVisitor.cs b/JavaToCSharp/Statements/StatementVisitor.cs index 21ff885b..196cb9c9 100644 --- a/JavaToCSharp/Statements/StatementVisitor.cs +++ b/JavaToCSharp/Statements/StatementVisitor.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using com.github.javaparser.ast.stmt; +using com.github.javaparser.ast.stmt; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace JavaToCSharp.Statements; @@ -48,11 +45,12 @@ static StatementVisitor() protected abstract StatementSyntax? Visit(ConversionContext context, Statement statement); - public static List VisitStatements(ConversionContext context, IEnumerable? statements) => - statements == null - ? new List() + public static List VisitStatements(ConversionContext context, IEnumerable? statements) + => statements is null + ? [] : statements.Select(statement => VisitStatement(context, statement)) - .Where(syntax => syntax != null)!.ToList(); + .OfType() // filter out nulls + .ToList(); public static StatementSyntax? VisitStatement(ConversionContext context, Statement statement) { diff --git a/JavaToCSharp/Statements/SwitchStatementVisitor.cs b/JavaToCSharp/Statements/SwitchStatementVisitor.cs index 42e2db25..21612f24 100644 --- a/JavaToCSharp/Statements/SwitchStatementVisitor.cs +++ b/JavaToCSharp/Statements/SwitchStatementVisitor.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using System.Linq; -using com.github.javaparser.ast.expr; +using com.github.javaparser.ast.expr; using com.github.javaparser.ast.stmt; using JavaToCSharp.Expressions; using Microsoft.CodeAnalysis.CSharp; @@ -14,6 +12,7 @@ public class SwitchStatementVisitor : StatementVisitor { var selector = switchStmt.getSelector(); var selectorSyntax = ExpressionVisitor.VisitExpression(context, selector); + if (selectorSyntax is null) { return null; @@ -21,8 +20,10 @@ public class SwitchStatementVisitor : StatementVisitor var cases = switchStmt.getEntries().ToList(); - if (cases == null) + if (cases is null) + { return SyntaxFactory.SwitchStatement(selectorSyntax, SyntaxFactory.List()); + } var caseSyntaxes = new List(); @@ -58,9 +59,9 @@ public class SwitchStatementVisitor : StatementVisitor { var labelSyntaxes = labels .Select(i => ExpressionVisitor.VisitExpression(context, i)) - .Where(i => i != null) - .Select(i => (SwitchLabelSyntax)SyntaxFactory.CaseSwitchLabel(i!)); - + .OfType() + .Select(SwitchLabelSyntax (i) => SyntaxFactory.CaseSwitchLabel(i)); + var caseSyntax = SyntaxFactory.SwitchSection( SyntaxFactory.List(labelSyntaxes.ToList()), SyntaxFactory.List(syntaxes.AsEnumerable())); diff --git a/JavaToCSharp/Statements/TryStatementVisitor.cs b/JavaToCSharp/Statements/TryStatementVisitor.cs index 1650d408..e842134b 100644 --- a/JavaToCSharp/Statements/TryStatementVisitor.cs +++ b/JavaToCSharp/Statements/TryStatementVisitor.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using com.github.javaparser; +using com.github.javaparser; using com.github.javaparser.ast.expr; using com.github.javaparser.ast.stmt; using com.github.javaparser.ast.type; @@ -15,7 +12,7 @@ public class TryStatementVisitor : StatementVisitor { public override StatementSyntax Visit(ConversionContext context, TryStmt tryStmt) { - var resources = tryStmt.getResources().ToList() ?? new List(); + var resources = tryStmt.getResources().ToList() ?? []; var tryBlock = tryStmt.getTryBlock(); var tryStatements = tryBlock.getStatements().ToList(); @@ -57,19 +54,18 @@ public override StatementSyntax Visit(ConversionContext context, TryStmt tryStmt var variable = varDecl.getVariable(0); var variableInit = variable.getInitializer().FromRequiredOptional(); - + var initSyntax = ExpressionVisitor.VisitExpression(context, variableInit) ?? throw new InvalidOperationException("Unable to parse try-with-resources variable initializer"); - + result = SyntaxFactory.UsingStatement(result) .WithDeclaration( SyntaxFactory.VariableDeclaration( SyntaxFactory.ParseTypeName(TypeHelper.ConvertType(variable.getType())), - SyntaxFactory.SeparatedList(new[] - { + SyntaxFactory.SeparatedList([ SyntaxFactory.VariableDeclarator(variable.getNameAsString()) .WithInitializer(SyntaxFactory.EqualsValueClause(initSyntax)) - }) + ]) )); } else @@ -81,13 +77,13 @@ public override StatementSyntax Visit(ConversionContext context, TryStmt tryStmt if (tryStmt.getFinallyBlock().isPresent() || tryStmt.getCatchClauses().ToList()?.Count > 0) { - result = TransformTryBlock(context, tryStmt, new[] { result }); + result = TransformTryBlock(context, tryStmt, [result]); } return result; } - private static StatementSyntax TransformTryBlock(ConversionContext context, TryStmt tryStmt, + private static TryStatementSyntax TransformTryBlock(ConversionContext context, TryStmt tryStmt, IEnumerable tryBlockStatements) { var catches = tryStmt.getCatchClauses().ToList(); @@ -95,14 +91,14 @@ private static StatementSyntax TransformTryBlock(ConversionContext context, TryS var trySyn = SyntaxFactory.TryStatement() .AddBlockStatements(tryBlockStatements.ToArray()); - if (catches != null) + if (catches is not null) { foreach (var catchClause in catches) { var paramType = catchClause.getParameter().getType(); if (paramType is UnionType) { - var nodes = paramType.getChildNodes()?.ToList() ?? new List(); + var nodes = paramType.getChildNodes()?.ToList() ?? []; foreach (var node in nodes) { var referenceTypeName = node.getElementType().ToString(); @@ -119,8 +115,10 @@ private static StatementSyntax TransformTryBlock(ConversionContext context, TryS var finallyBlock = tryStmt.getFinallyBlock().FromOptional(); - if (finallyBlock == null) + if (finallyBlock is null) + { return trySyn; + } var finallyStatements = finallyBlock.getStatements().ToList(); var finallyConverted = VisitStatements(context, finallyStatements); @@ -154,4 +152,4 @@ private static TryStatementSyntax AddCatches(ConversionContext context, CatchCla return trySyn; } -} \ No newline at end of file +} diff --git a/JavaToCSharp/Statements/TypeDeclarationStatementVisitor.cs b/JavaToCSharp/Statements/TypeDeclarationStatementVisitor.cs index 4fd737d6..666460a3 100644 --- a/JavaToCSharp/Statements/TypeDeclarationStatementVisitor.cs +++ b/JavaToCSharp/Statements/TypeDeclarationStatementVisitor.cs @@ -13,11 +13,12 @@ public class TypeDeclarationStatementVisitor : StatementVisitor { var expr = whileStmt.getCondition(); var syntax = ExpressionVisitor.VisitExpression(context, expr); + if (syntax is null) { return null; diff --git a/JavaToCSharp/SyntaxMapping.cs b/JavaToCSharp/SyntaxMapping.cs index 50e18c08..08d8f5dc 100644 --- a/JavaToCSharp/SyntaxMapping.cs +++ b/JavaToCSharp/SyntaxMapping.cs @@ -21,6 +21,7 @@ private void Validate() ValidateMethodMapping(VoidMethodMappings); ValidateMethodMapping(NonVoidMethodMappings); } + private static void ValidateMethodMapping(Dictionary mapping) { // Throw exception if any of the requirements are not meet @@ -39,5 +40,4 @@ private static void ValidateMethodMapping(Dictionary mapping) } } } - } diff --git a/JavaToCSharp/TypeHelper.cs b/JavaToCSharp/TypeHelper.cs index 0eedaa70..6bb5f6bb 100644 --- a/JavaToCSharp/TypeHelper.cs +++ b/JavaToCSharp/TypeHelper.cs @@ -62,16 +62,7 @@ public static string ConvertType(Type type) } public static string ConvertType(string typeName) - { - return TypeNameParser.ParseTypeName(typeName, s => - { - if (_typeNameConversions.TryGetValue(s, out string? converted)) - { - return converted; - } - return s; - }); - } + => TypeNameParser.ParseTypeName(typeName, s => _typeNameConversions.TryGetValue(s, out string? converted) ? converted : s); public static TypeSyntax ConvertTypeSyntax(Type type, int arrayRank) { @@ -202,13 +193,17 @@ private static SeparatedSyntaxList GetSeparatedListFromArguments public static IEnumerable GetTypeParameterListConstraints(List typeParams) { var typeParameterConstraints = new List(); + foreach (TypeParameter typeParam in typeParams) { if (typeParam.getTypeBound().size() > 0) { var typeConstraintsSyntax = new SeparatedSyntaxList(); + foreach (ClassOrInterfaceType bound in typeParam.getTypeBound()) + { typeConstraintsSyntax = typeConstraintsSyntax.Add(SyntaxFactory.TypeConstraint(SyntaxFactory.ParseTypeName(bound.asString()))); + } var typeIdentifier = SyntaxFactory.IdentifierName(typeParam.getName().asString()); var parameterConstraintClauseSyntax = SyntaxFactory.TypeParameterConstraintClause(typeIdentifier, typeConstraintsSyntax); @@ -216,6 +211,7 @@ public static IEnumerable GetTypeParameterL typeParameterConstraints.Add(parameterConstraintClauseSyntax); } } + return typeParameterConstraints; } @@ -237,16 +233,21 @@ public static bool TryTransformMethodCall(ConversionContext context, MethodCallE switch (methodName.getIdentifier()) { case "length" when args.size() == 0: + { var scopeSyntaxLength = ExpressionVisitor.VisitExpression(context, scope); transformedSyntax = ReplaceMethodByProperty(scopeSyntaxLength, "Length"); return true; + } case "size" when args.size() == 0: + { var scopeSyntaxSize = ExpressionVisitor.VisitExpression(context, scope); transformedSyntax = ReplaceMethodByProperty(scopeSyntaxSize, "Count"); return true; + } case "get" when args.size() == 1: + { var scopeSyntaxGet = ExpressionVisitor.VisitExpression(context, scope); if (scopeSyntaxGet is null) { @@ -256,8 +257,10 @@ public static bool TryTransformMethodCall(ConversionContext context, MethodCallE transformedSyntax = ReplaceGetByIndexAccess(context, scopeSyntaxGet, args); return true; + } case "set" when args.size() == 2: + { var scopeSyntaxSet = ExpressionVisitor.VisitExpression(context, scope); if (scopeSyntaxSet is null) { @@ -267,13 +270,13 @@ public static bool TryTransformMethodCall(ConversionContext context, MethodCallE transformedSyntax = ReplaceSetByIndexAccess(context, scopeSyntaxSet, args); return true; + } } } transformedSyntax = null; return false; - static MemberAccessExpressionSyntax? ReplaceMethodByProperty(ExpressionSyntax? scopeSyntax, string identifier) { if (scopeSyntax is null) @@ -304,7 +307,7 @@ static ExpressionSyntax ReplaceGetByIndexAccess(ConversionContext context, Expre java.util.List args) { // Replace expr.Set(i,v) by expr[i] = v - var argsList = args.ToList() ?? new List(); + var argsList = args.ToList() ?? []; var left = SyntaxFactory.ElementAccessExpression( scopeSyntax, SyntaxFactory.BracketedArgumentList(GetSeparatedListFromArguments(context, argsList.Take(1))) diff --git a/JavaToCSharp/TypeNameParser.cs b/JavaToCSharp/TypeNameParser.cs index ada68811..353bab20 100644 --- a/JavaToCSharp/TypeNameParser.cs +++ b/JavaToCSharp/TypeNameParser.cs @@ -1,10 +1,9 @@ -using System; -using System.Text; +using System.Text; using System.Text.RegularExpressions; namespace JavaToCSharp; -public static class TypeNameParser +public static partial class TypeNameParser { private enum TokenType { @@ -20,7 +19,8 @@ private enum TokenType QuestionMark } - private static readonly Regex _tokenizePattern = new(@"\w+|\[|\]|<|>|,|\?", RegexOptions.Compiled); + [GeneratedRegex(@"\w+|\[|\]|<|>|,|\?", RegexOptions.Compiled)] + private static partial Regex TokenizePattern { get; } private static (string, TokenType)[]? _tokens; private static (string text, TokenType type) _token; @@ -53,7 +53,7 @@ internal static string ParseTypeName(string typename, Func trans private static (string, TokenType)[] Tokenize(string typeName) { - var matches = _tokenizePattern.Matches(typeName); + var matches = TokenizePattern.Matches(typeName); var tokens = new (string, TokenType)[matches.Count]; for (int i = 0; i < matches.Count; i++) { diff --git a/JavaToCSharp/UsingsHelper.cs b/JavaToCSharp/UsingsHelper.cs index 5b2a75e4..a4630ff6 100644 --- a/JavaToCSharp/UsingsHelper.cs +++ b/JavaToCSharp/UsingsHelper.cs @@ -25,7 +25,7 @@ public static IEnumerable GetUsings(ConversionContext cont var nameSpace = TypeHelper.Capitalize(importNameWithoutClassName); // Override namespace if a non empty mapping is found (mapping to empty string removes the import) - if (options != null && options.SyntaxMappings.ImportMappings.TryGetValue(importName, out var mappedNamespace)) + if (options is not null && options.SyntaxMappings.ImportMappings.TryGetValue(importName, out var mappedNamespace)) { if (string.IsNullOrEmpty(mappedNamespace)) { @@ -51,7 +51,7 @@ public static IEnumerable GetUsings(ConversionContext cont .Select(ns => SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(ns)).NormalizeWhitespace().WithTrailingNewLines())); } - if (namespaceNameSyntax != null) + if (namespaceNameSyntax is not null) { foreach (var staticUsing in options?.StaticUsingEnumNames ?? []) { @@ -90,7 +90,5 @@ public bool Equals(UsingDirectiveSyntax? x, UsingDirectiveSyntax? y) } public int GetHashCode(UsingDirectiveSyntax obj) - { - return HashCode.Combine(obj.Alias?.ToString() ?? "", obj.Name?.ToString() ?? ""); - } + => HashCode.Combine(obj.Alias?.ToString() ?? "", obj.Name?.ToString() ?? ""); } diff --git a/JavaToCSharpCli/JavaToCSharpCli.csproj b/JavaToCSharpCli/JavaToCSharpCli.csproj index 6c36c40a..564e41a9 100644 --- a/JavaToCSharpCli/JavaToCSharpCli.csproj +++ b/JavaToCSharpCli/JavaToCSharpCli.csproj @@ -6,7 +6,7 @@ latest enable enable - nullable + true diff --git a/JavaToCSharpCli/Program.cs b/JavaToCSharpCli/Program.cs index 5c831389..d74a0fc3 100644 --- a/JavaToCSharpCli/Program.cs +++ b/JavaToCSharpCli/Program.cs @@ -1,5 +1,4 @@ using System.CommandLine; -using System.CommandLine.Invocation; using JavaToCSharp; using Microsoft.Extensions.Logging; @@ -133,18 +132,20 @@ private static Command CreateFileCommand() DefaultValueFactory = _ => null, }; - var fileCommand = new Command("file", "Convert a Java file to C#"); - fileCommand.Arguments.Add(inputArgument); - fileCommand.Arguments.Add(outputArgument); + var fileCommand = new Command("file", "Convert a Java file to C#") + { + inputArgument, + outputArgument, + }; fileCommand.SetAction(context => { - var input = context.GetValue(inputArgument); + var input = context.GetRequiredValue(inputArgument); var output = context.GetValue(outputArgument); var options = GetJavaConversionOptions(context); - ConvertToCSharpFile(input!, output, options); + ConvertToCSharpFile(input, output, options); }); return fileCommand; @@ -178,7 +179,7 @@ private static JavaConversionOptions GetJavaConversionOptions(ParseResult contex options.AddUsing("System.Text"); } - foreach (string ns in context.GetValue(_addUsingsOption) ?? new List()) + foreach (string ns in context.GetValue(_addUsingsOption) ?? []) { options.AddUsing(ns); } @@ -203,26 +204,28 @@ private static Command CreateDirectoryCommand() { var inputArgument = new Argument("input") { - Description = "A directory containing Java source code files to convert" + Description = "A directory containing Java source code files to convert", }; var outputArgument = new Argument("output") { - Description = "Path to place the C# output files" + Description = "Path to place the C# output files", }; - var dirCommand = new Command("dir", "Convert a directory containing Java files to C#"); - dirCommand.Arguments.Add(inputArgument); - dirCommand.Arguments.Add(outputArgument); + var dirCommand = new Command("dir", "Convert a directory containing Java files to C#") + { + inputArgument, + outputArgument, + }; dirCommand.SetAction(context => { - var input = context.GetValue(inputArgument); - var output = context.GetValue(outputArgument); + var input = context.GetRequiredValue(inputArgument); + var output = context.GetRequiredValue(outputArgument); var options = GetJavaConversionOptions(context); - ConvertToCSharpDir(input!, output!, options); + ConvertToCSharpDir(input, output, options); }); return dirCommand; diff --git a/JavaToCSharpGui/App.axaml b/JavaToCSharpGui/App.axaml index 3128bd0d..29a53652 100644 --- a/JavaToCSharpGui/App.axaml +++ b/JavaToCSharpGui/App.axaml @@ -6,11 +6,11 @@ RequestedThemeVariant="Default"> 14 - Cascadia Code,SF Mono,DejaVu Sans Mono,Menlo,Consolas + Cascadia Code,SF Mono,DejaVu Sans Mono,Menlo,Consolas - - + + diff --git a/JavaToCSharpGui/App.axaml.cs b/JavaToCSharpGui/App.axaml.cs index fc990f8e..5ab33082 100644 --- a/JavaToCSharpGui/App.axaml.cs +++ b/JavaToCSharpGui/App.axaml.cs @@ -15,13 +15,13 @@ public override void Initialize() public override void OnFrameworkInitializationCompleted() { - if(ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { // Line below is needed to remove Avalonia data validation. // Without this line you will get duplicate validations from both Avalonia and CT BindingPlugins.DataValidators.RemoveAt(0); - desktop.MainWindow = new MainWindow(); + desktop.MainWindow = new MainWindow(); base.OnFrameworkInitializationCompleted(); } } -} \ No newline at end of file +} diff --git a/JavaToCSharpGui/Infrastructure/ITextClipboard.cs b/JavaToCSharpGui/Infrastructure/ITextClipboard.cs index 0c71366e..9a5cb9d6 100644 --- a/JavaToCSharpGui/Infrastructure/ITextClipboard.cs +++ b/JavaToCSharpGui/Infrastructure/ITextClipboard.cs @@ -8,7 +8,7 @@ public interface ITextClipboard /// /// Gets the clipboard's text. /// - /// A Task representing the async operation that returns the clipboard text. + /// A Task representing the async operation. The result is the clipboard text, or null if unavailable. Task GetTextAsync(); /// diff --git a/JavaToCSharpGui/Infrastructure/IUIDispatcher.cs b/JavaToCSharpGui/Infrastructure/IUIDispatcher.cs index 44e8d0bf..33b31d20 100644 --- a/JavaToCSharpGui/Infrastructure/IUIDispatcher.cs +++ b/JavaToCSharpGui/Infrastructure/IUIDispatcher.cs @@ -3,7 +3,7 @@ namespace JavaToCSharpGui.Infrastructure; /// -/// Provides acces to the UI thread. +/// Provides access to the UI thread. /// public interface IUIDispatcher { diff --git a/JavaToCSharpGui/Infrastructure/TextClipboard.cs b/JavaToCSharpGui/Infrastructure/TextClipboard.cs index 4c91edad..3f5302d2 100644 --- a/JavaToCSharpGui/Infrastructure/TextClipboard.cs +++ b/JavaToCSharpGui/Infrastructure/TextClipboard.cs @@ -3,29 +3,27 @@ namespace JavaToCSharpGui.Infrastructure; /// -internal class TextClipboard : ITextClipboard +internal class TextClipboard(IClipboard? clipboard) : ITextClipboard { - private readonly IClipboard? _clipboard; - - public TextClipboard(IClipboard? clipboard) => _clipboard = clipboard; - /// public async Task GetTextAsync() { - if (_clipboard is null) + if (clipboard is null) { return null; } - return await _clipboard.GetTextAsync(); + + return await clipboard.TryGetTextAsync(); } /// public async Task SetTextAsync(string? text) { - if(_clipboard is null) + if (clipboard is null) { return; } - await _clipboard.SetTextAsync(text); + + await clipboard.SetTextAsync(text); } } diff --git a/JavaToCSharpGui/Infrastructure/UIDispatcher.cs b/JavaToCSharpGui/Infrastructure/UIDispatcher.cs index efc1bbd4..08da38e1 100644 --- a/JavaToCSharpGui/Infrastructure/UIDispatcher.cs +++ b/JavaToCSharpGui/Infrastructure/UIDispatcher.cs @@ -5,19 +5,12 @@ using Avalonia.Threading; /// -public class UIDispatcher : IUIDispatcher +public class UIDispatcher(IDispatcher dispatcher) : IUIDispatcher { - private readonly IDispatcher _dispatcher; - - public UIDispatcher(IDispatcher dispatcher) - { - _dispatcher = dispatcher; - } - /// public async Task InvokeAsync(Action callback, DispatcherPriority priority) { - if (_dispatcher is Dispatcher avaloniaDispatcher) + if (dispatcher is Dispatcher avaloniaDispatcher) { await avaloniaDispatcher.InvokeAsync(callback, priority); } diff --git a/JavaToCSharpGui/JavaToCSharpGui.csproj b/JavaToCSharpGui/JavaToCSharpGui.csproj index 170f0084..334d7f4c 100644 --- a/JavaToCSharpGui/JavaToCSharpGui.csproj +++ b/JavaToCSharpGui/JavaToCSharpGui.csproj @@ -8,26 +8,23 @@ latest enable enable - Nullable + true true + 11.3.8 - + + + + + + - - - - - - - - - diff --git a/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs b/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs index 7372a7f9..ac058707 100644 --- a/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs +++ b/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs @@ -188,6 +188,7 @@ await Task.Run(async () => foreach (var jFile in FolderInputFiles.Where(static x => x.Directory is not null)) { + // ! null checked above string jPath = jFile.Directory!.FullName; string jOutPath = $"{outDirFullName}{jPath[subStartIndex..]}"; string jOutFileName = Path.GetFileNameWithoutExtension(jFile.Name) + ".cs"; @@ -314,23 +315,83 @@ private async Task OpenFileDialog() } [RelayCommand] - private async Task PasteInput() + private async Task PasteJavaCode() { if (_clipboard is null) { return; } - var text = await _clipboard.GetTextAsync(); - if (!string.IsNullOrEmpty(text)) + string? clipboardText = await _clipboard.GetTextAsync(); + if (clipboardText is null) { - JavaText.Text = text; - ConversionStateLabel = "Pasted Java code from clipboard!"; + ShowMessage("Clipboard is empty or unavailable.", "Paste Error"); + return; + } - await Task.Delay(2000); + JavaText.Text = clipboardText; + ConversionStateLabel = "Pasted Java code from clipboard!"; + + await Task.Delay(2000); + + await _dispatcher.InvokeAsync(() => { ConversionStateLabel = ""; }, DispatcherPriority.Background); + } - await _dispatcher.InvokeAsync(() => { ConversionStateLabel = ""; }, DispatcherPriority.Background); + [RelayCommand] + private async Task ClipboardConvert() + { + if (_clipboard is null) + { + return; } + + // Get clipboard text + string? clipboardText = await _clipboard.GetTextAsync(); + if (clipboardText is null) + { + ShowMessage("Clipboard is empty or unavailable.", "Clipboard Convert Error"); + return; + } + + // Set Java text + JavaText.Text = clipboardText; + + // Perform conversion + CurrentOptions.Options.WarningEncountered += Options_WarningEncountered; + CurrentOptions.Options.StateChanged += Options_StateChanged; + + IsConvertEnabled = false; + _usingFolderConvert = false; + + await Task.Run(async () => + { + try + { + string? csharp = JavaToCSharpConverter.ConvertText(clipboardText, CurrentOptions.Options); + await DispatcherInvoke(() => CSharpText.Text = csharp ?? ""); + + // Copy result to clipboard + await _clipboard.SetTextAsync(csharp ?? ""); + ConversionStateLabel = "Conversion complete! C# code copied to clipboard."; + + await Task.Delay(2000); + await _dispatcher.InvokeAsync(() => { ConversionStateLabel = ""; }, DispatcherPriority.Background); + } + catch (Exception ex) + { + await DispatcherInvoke(() => + ShowMessage($"There was an error converting the text to C#: {ex.GetBaseException().Message}", + "Conversion Error")); + + ConversionStateLabel = ""; + } + finally + { + await DispatcherInvoke(() => IsConvertEnabled = true); + CurrentOptions.Options.WarningEncountered -= Options_WarningEncountered; + CurrentOptions.Options.StateChanged -= Options_StateChanged; + } + }); } [RelayCommand] @@ -356,7 +417,7 @@ private async Task SaveOutput() { IStorageFolder? startLocation = null; - if (Path.GetDirectoryName(OpenPath) is string dir) + if (Path.GetDirectoryName(OpenPath) is { } dir) { startLocation = await _storageProvider.TryGetFolderFromPathAsync(dir); } diff --git a/JavaToCSharpGui/Views/AboutWindow.axaml.cs b/JavaToCSharpGui/Views/AboutWindow.axaml.cs index 626d9114..ec5a2e93 100644 --- a/JavaToCSharpGui/Views/AboutWindow.axaml.cs +++ b/JavaToCSharpGui/Views/AboutWindow.axaml.cs @@ -7,22 +7,18 @@ namespace JavaToCSharpGui.Views; public partial class AboutWindow : Window { - private readonly string _version; - public AboutWindow() { var assembly = Assembly.GetExecutingAssembly(); - _version = assembly.GetCustomAttribute()?.InformationalVersion + VersionString = assembly.GetCustomAttribute()?.InformationalVersion ?? assembly.GetName().Version?.ToString() ?? "Unknown"; InitializeComponent(); DataContext = this; - - } - public string VersionString => $"Version {_version}"; + public string VersionString => $"Version {field}"; private void GitHubLinkTapped(object? sender, TappedEventArgs e) => Process.Start(new ProcessStartInfo { diff --git a/JavaToCSharpGui/Views/MainWindow.axaml b/JavaToCSharpGui/Views/MainWindow.axaml index 167ce988..ab9e6a54 100644 --- a/JavaToCSharpGui/Views/MainWindow.axaml +++ b/JavaToCSharpGui/Views/MainWindow.axaml @@ -59,27 +59,27 @@ Java Source Code Input: - - File: + + + File: - - - + + + + C# Output: