From 6cb308996d6143a73a9003625e8c0ec66d3e3f0e Mon Sep 17 00:00:00 2001 From: Paul Irwin Date: Fri, 14 Nov 2025 14:06:01 -0700 Subject: [PATCH 1/6] Upgrade to .NET 10 and update NuGet packages, #138 --- JavaToCSharp.Tests/JavaToCSharp.Tests.csproj | 3 +- JavaToCSharp.sln | 55 -------------- JavaToCSharp.slnx | 12 ++++ ...tSettings => JavaToCSharp.slnx.DotSettings | 2 + JavaToCSharp/JavaToCSharp.csproj | 4 +- JavaToCSharpCli/Program.cs | 72 +++++++++---------- JavaToCSharpGui/App.axaml | 8 +-- JavaToCSharpGui/App.axaml.cs | 6 +- JavaToCSharpGui/JavaToCSharpGui.csproj | 13 ++++ JavaToCSharpGui/Views/AboutWindow.axaml.cs | 2 - 10 files changed, 75 insertions(+), 102 deletions(-) delete mode 100644 JavaToCSharp.sln create mode 100644 JavaToCSharp.slnx rename JavaToCSharp.sln.DotSettings => JavaToCSharp.slnx.DotSettings (65%) diff --git a/JavaToCSharp.Tests/JavaToCSharp.Tests.csproj b/JavaToCSharp.Tests/JavaToCSharp.Tests.csproj index 54e5aede..62109423 100644 --- a/JavaToCSharp.Tests/JavaToCSharp.Tests.csproj +++ b/JavaToCSharp.Tests/JavaToCSharp.Tests.csproj @@ -21,12 +21,13 @@ all + - + 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/JavaToCSharp.csproj b/JavaToCSharp/JavaToCSharp.csproj index 66903f14..ff20af59 100644 --- a/JavaToCSharp/JavaToCSharp.csproj +++ b/JavaToCSharp/JavaToCSharp.csproj @@ -7,7 +7,7 @@ nullable Paul Irwin A Java to C# converter. - Copyright 2021-2023, Paul Irwin + Copyright 2021-2025, Paul Irwin MIT https://github.com/paulirwin/JavaToCSharp latest @@ -18,6 +18,8 @@ + + diff --git a/JavaToCSharpCli/Program.cs b/JavaToCSharpCli/Program.cs index 5c831389..8730d375 100644 --- a/JavaToCSharpCli/Program.cs +++ b/JavaToCSharpCli/Program.cs @@ -95,26 +95,28 @@ public static async Task Main(string[] args) { var rootCommand = new RootCommand("Java to C# Converter") { - Description = "A syntactic transformer of source code from Java to C#.", + Description = "A syntactic transformer of source code from Java to C#." }; - rootCommand.Subcommands.Add(CreateFileCommand()); - rootCommand.Subcommands.Add(CreateDirectoryCommand()); + rootCommand.Add(CreateFileCommand()); + rootCommand.Add(CreateDirectoryCommand()); - rootCommand.Options.Add(_includeSubdirectoriesOption); - rootCommand.Options.Add(_includeUsingsOption); - rootCommand.Options.Add(_includeNamespaceOption); - rootCommand.Options.Add(_includeCommentsOption); - rootCommand.Options.Add(_useDebugAssertOption); - rootCommand.Options.Add(_startInterfaceNamesWithIOption); - rootCommand.Options.Add(_commentUnrecognizedCodeOption); - rootCommand.Options.Add(_systemOutToConsoleOption); - rootCommand.Options.Add(_fileScopedNamespacesOption); - rootCommand.Options.Add(_clearDefaultUsingsOption); - rootCommand.Options.Add(_addUsingsOption); - rootCommand.Options.Add(_mappingsFileNameOption); + rootCommand.Add(_includeSubdirectoriesOption); + rootCommand.Add(_includeUsingsOption); + rootCommand.Add(_includeNamespaceOption); + rootCommand.Add(_includeCommentsOption); + rootCommand.Add(_useDebugAssertOption); + rootCommand.Add(_startInterfaceNamesWithIOption); + rootCommand.Add(_commentUnrecognizedCodeOption); + rootCommand.Add(_systemOutToConsoleOption); + rootCommand.Add(_fileScopedNamespacesOption); + rootCommand.Add(_clearDefaultUsingsOption); + rootCommand.Add(_addUsingsOption); + rootCommand.Add(_mappingsFileNameOption); - await rootCommand.Parse(args).InvokeAsync(); + var parseResult = rootCommand.Parse(args); + + await parseResult.InvokeAsync(); // flush logs _loggerFactory.Dispose(); @@ -133,18 +135,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 +182,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 +207,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; @@ -253,17 +259,13 @@ private static void ConvertToCSharpDir(DirectoryInfo inputDirectory, DirectoryIn } } else - { _logger.LogError("Java input folder {path} doesn't exist!", inputDirectory); - } } private static void ConvertToCSharpFile(FileSystemInfo inputFile, FileSystemInfo? outputFile, JavaConversionOptions options, bool overwrite = true) { if (!overwrite && outputFile is { Exists: true }) - { _logger.LogInformation("{outputFilePath} exists, skip to next.", outputFile); - } else if (inputFile.Exists) { try @@ -301,9 +303,7 @@ private static void ConvertToCSharpFile(FileSystemInfo inputFile, FileSystemInfo } } else - { _logger.LogError("Java input file {filePath} doesn't exist!", inputFile.FullName); - } } private static void OutputFileOrPrint(string? fileName, string contents) diff --git a/JavaToCSharpGui/App.axaml b/JavaToCSharpGui/App.axaml index 3128bd0d..a8e8c4a5 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/JavaToCSharpGui.csproj b/JavaToCSharpGui/JavaToCSharpGui.csproj index 170f0084..3d3f8df5 100644 --- a/JavaToCSharpGui/JavaToCSharpGui.csproj +++ b/JavaToCSharpGui/JavaToCSharpGui.csproj @@ -10,6 +10,7 @@ enable Nullable true + 11.3.8 @@ -31,6 +32,18 @@ + + + + + + + + + + + + diff --git a/JavaToCSharpGui/Views/AboutWindow.axaml.cs b/JavaToCSharpGui/Views/AboutWindow.axaml.cs index 626d9114..42cbb9c3 100644 --- a/JavaToCSharpGui/Views/AboutWindow.axaml.cs +++ b/JavaToCSharpGui/Views/AboutWindow.axaml.cs @@ -18,8 +18,6 @@ public AboutWindow() InitializeComponent(); DataContext = this; - - } public string VersionString => $"Version {_version}"; From 9d4c8515edb7a1451bcb2b1c355222bb87bf86a0 Mon Sep 17 00:00:00 2001 From: Paul Irwin Date: Fri, 14 Nov 2025 14:25:59 -0700 Subject: [PATCH 2/6] Add paste button, #136 --- .../Infrastructure/ITextClipboard.cs | 6 +++++ .../Infrastructure/TextClipboard.cs | 10 +++++++++ .../ViewModels/MainWindowViewModel.cs | 19 +++++++++------- JavaToCSharpGui/Views/MainWindow.axaml | 22 +++++++++---------- 4 files changed, 38 insertions(+), 19 deletions(-) diff --git a/JavaToCSharpGui/Infrastructure/ITextClipboard.cs b/JavaToCSharpGui/Infrastructure/ITextClipboard.cs index 0c71366e..3ad159de 100644 --- a/JavaToCSharpGui/Infrastructure/ITextClipboard.cs +++ b/JavaToCSharpGui/Infrastructure/ITextClipboard.cs @@ -17,4 +17,10 @@ public interface ITextClipboard /// The text to be copied to the clipboard. /// A Task representing the async operation. Task SetTextAsync(string? text); + + /// + /// Gets the clipboard's text. + /// + /// A Task representing the async operation. The result is the clipboard text, or null if unavailable. + Task GetTextAsync(); } diff --git a/JavaToCSharpGui/Infrastructure/TextClipboard.cs b/JavaToCSharpGui/Infrastructure/TextClipboard.cs index 4c91edad..d2f979a5 100644 --- a/JavaToCSharpGui/Infrastructure/TextClipboard.cs +++ b/JavaToCSharpGui/Infrastructure/TextClipboard.cs @@ -28,4 +28,14 @@ public async Task SetTextAsync(string? text) } await _clipboard.SetTextAsync(text); } + + /// + public async Task GetTextAsync() + { + if (_clipboard is null) + { + return null; + } + return await _clipboard.GetTextAsync(); + } } diff --git a/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs b/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs index 7372a7f9..ec3fe531 100644 --- a/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs +++ b/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs @@ -314,23 +314,26 @@ 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 _dispatcher.InvokeAsync(() => { ConversionStateLabel = ""; }, DispatcherPriority.Background); - } + await Task.Delay(2000); + + await _dispatcher.InvokeAsync(() => { ConversionStateLabel = ""; }, DispatcherPriority.Background); } [RelayCommand] diff --git a/JavaToCSharpGui/Views/MainWindow.axaml b/JavaToCSharpGui/Views/MainWindow.axaml index 167ce988..c162ff9c 100644 --- a/JavaToCSharpGui/Views/MainWindow.axaml +++ b/JavaToCSharpGui/Views/MainWindow.axaml @@ -59,27 +59,27 @@ Java Source Code Input: - - File: + + + File: - - Date: Fri, 14 Nov 2025 14:29:50 -0700 Subject: [PATCH 3/6] Add clipboard convert button, #135 --- .../ViewModels/MainWindowViewModel.cs | 57 +++++++++++++++++++ JavaToCSharpGui/Views/MainWindow.axaml | 14 +++-- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs b/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs index ec3fe531..ce5f4da4 100644 --- a/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs +++ b/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs @@ -336,6 +336,63 @@ private async Task PasteJavaCode() 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] private async Task CopyOutput() { diff --git a/JavaToCSharpGui/Views/MainWindow.axaml b/JavaToCSharpGui/Views/MainWindow.axaml index c162ff9c..ab9e6a54 100644 --- a/JavaToCSharpGui/Views/MainWindow.axaml +++ b/JavaToCSharpGui/Views/MainWindow.axaml @@ -91,10 +91,16 @@ FontFamily="{CompiledBinding MonospaceFontFamily}" /> - + + + + C# Output: Date: Wed, 10 Dec 2025 21:41:33 -0700 Subject: [PATCH 4/6] C# 14 code cleanup --- JavaToCSharp.Tests/CommentTests.cs | 1 - JavaToCSharp.Tests/JavaToCSharp.Tests.csproj | 3 +- JavaToCSharp/CommentsHelper.cs | 46 ++++--- JavaToCSharp/ConversionContext.cs | 18 +-- .../ConversionStateChangedEventArgs.cs | 13 +- JavaToCSharp/ConversionWarningEventArgs.cs | 16 +-- .../AnnotationDeclarationVisitor.cs | 4 +- .../Declarations/BodyDeclarationVisitor.cs | 4 +- .../ClassOrInterfaceDeclarationVisitor.cs | 16 +-- .../ConstructorDeclarationVisitor.cs | 2 +- .../Declarations/EnumDeclarationVisitor.cs | 2 +- .../Declarations/FieldDeclarationVisitor.cs | 2 +- .../InitializerDeclarationVisitor.cs | 4 +- .../Declarations/MethodDeclarationVisitor.cs | 25 ++-- .../ArrayAccessExpressionVisitor.cs | 6 +- .../ArrayCreationExpressionVisitor.cs | 24 ++-- .../ArrayInitializerExpressionVisitor.cs | 6 +- JavaToCSharp/Expressions/ExpressionVisitor.cs | 6 +- .../FieldAccessExpressionVisitor.cs | 2 +- .../MethodCallExpressionVisitor.cs | 10 +- .../MethodReferenceExpressionVisitor.cs | 6 +- .../ObjectCreationExpressionVisitor.cs | 12 +- JavaToCSharp/Extensions.cs | 128 ++++++++++-------- JavaToCSharp/JavaToCSharp.csproj | 53 ++++---- JavaToCSharp/JavaToCSharpConverter.cs | 8 +- JavaToCSharp/Replacement.cs | 28 ++-- JavaToCSharp/SanitizingSyntaxRewriter.cs | 2 +- .../Statements/AssertStatementVisitor.cs | 14 +- .../Statements/ExpressionStatementVisitor.cs | 6 +- .../Statements/ForEachStatementVisitor.cs | 8 +- .../Statements/ForStatementVisitor.cs | 16 +-- JavaToCSharp/Statements/IfStatementVisitor.cs | 12 +- .../Statements/LabeledStatementVisitor.cs | 4 +- .../Statements/ReturnStatementVisitor.cs | 4 +- JavaToCSharp/Statements/StatementVisitor.cs | 14 +- .../Statements/SwitchStatementVisitor.cs | 15 +- .../Statements/TryStatementVisitor.cs | 30 ++-- .../TypeDeclarationStatementVisitor.cs | 5 +- .../Statements/WhileStatementVisitor.cs | 1 + JavaToCSharp/SyntaxMapping.cs | 2 +- JavaToCSharp/TypeHelper.cs | 27 ++-- JavaToCSharp/TypeNameParser.cs | 10 +- JavaToCSharp/UsingsHelper.cs | 8 +- JavaToCSharpCli/JavaToCSharpCli.csproj | 2 +- JavaToCSharpCli/Program.cs | 1 - .../Infrastructure/ITextClipboard.cs | 8 +- .../Infrastructure/IUIDispatcher.cs | 2 +- .../Infrastructure/TextClipboard.cs | 24 +--- .../Infrastructure/UIDispatcher.cs | 11 +- JavaToCSharpGui/JavaToCSharpGui.csproj | 28 +--- .../ViewModels/MainWindowViewModel.cs | 3 +- JavaToCSharpGui/Views/AboutWindow.axaml.cs | 6 +- 52 files changed, 325 insertions(+), 383 deletions(-) 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 62109423..51827f4d 100644 --- a/JavaToCSharp.Tests/JavaToCSharp.Tests.csproj +++ b/JavaToCSharp.Tests/JavaToCSharp.Tests.csproj @@ -6,7 +6,7 @@ enable latest enable - nullable + true @@ -21,7 +21,6 @@ all - 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 ff20af59..2cad3e2c 100644 --- a/JavaToCSharp/JavaToCSharp.csproj +++ b/JavaToCSharp/JavaToCSharp.csproj @@ -1,29 +1,28 @@  - - 4.0.0 - net10.0 - enable - enable - nullable - Paul Irwin - A Java to C# converter. - Copyright 2021-2025, 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 8730d375..8f029831 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; diff --git a/JavaToCSharpGui/Infrastructure/ITextClipboard.cs b/JavaToCSharpGui/Infrastructure/ITextClipboard.cs index 3ad159de..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(); /// @@ -17,10 +17,4 @@ public interface ITextClipboard /// The text to be copied to the clipboard. /// A Task representing the async operation. Task SetTextAsync(string? text); - - /// - /// Gets the clipboard's 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 d2f979a5..9cc8add4 100644 --- a/JavaToCSharpGui/Infrastructure/TextClipboard.cs +++ b/JavaToCSharpGui/Infrastructure/TextClipboard.cs @@ -3,39 +3,25 @@ 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); - } - - /// - public async Task GetTextAsync() - { - if (_clipboard is null) - { - return null; - } - return await _clipboard.GetTextAsync(); + 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 3d3f8df5..334d7f4c 100644 --- a/JavaToCSharpGui/JavaToCSharpGui.csproj +++ b/JavaToCSharpGui/JavaToCSharpGui.csproj @@ -8,7 +8,7 @@ latest enable enable - Nullable + true true 11.3.8 @@ -16,34 +16,18 @@ - - - - - - - - - - - - - - - - - - - - + + + - + + diff --git a/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs b/JavaToCSharpGui/ViewModels/MainWindowViewModel.cs index ce5f4da4..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"; @@ -416,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 42cbb9c3..ec5a2e93 100644 --- a/JavaToCSharpGui/Views/AboutWindow.axaml.cs +++ b/JavaToCSharpGui/Views/AboutWindow.axaml.cs @@ -7,12 +7,10 @@ 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"; @@ -20,7 +18,7 @@ public AboutWindow() DataContext = this; } - public string VersionString => $"Version {_version}"; + public string VersionString => $"Version {field}"; private void GitHubLinkTapped(object? sender, TappedEventArgs e) => Process.Start(new ProcessStartInfo { From 01dd9124472d3a25c090399f3c7fe64c1ff985b7 Mon Sep 17 00:00:00 2001 From: Paul Irwin Date: Wed, 10 Dec 2025 21:42:34 -0700 Subject: [PATCH 5/6] Update README --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index c4867912..b1a3a686 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,6 @@ These options may become enabled by default when the next LTS ships, as a major .NET Framework is no longer supported and will not be supported going forward. This includes not just for the core library (i.e. .NET Standard will not be supported) and running the CLI/GUI apps, but also for the C# code generation where applicable. -You should be running .NET LTS nowadays anyways (.NET 6+ at the time of writing). Bug fixes and features may be backported to the latest major version that targets an actively-supported, non-latest .NET LTS, but only based on community interest. From 9d3c4fc34173a210bd14cd157117d549f182bb57 Mon Sep 17 00:00:00 2001 From: Paul Irwin Date: Thu, 11 Dec 2025 07:04:53 -0700 Subject: [PATCH 6/6] Fix merge issues --- JavaToCSharpCli/Program.cs | 40 ++++++++++--------- JavaToCSharpGui/App.axaml | 2 +- .../Infrastructure/TextClipboard.cs | 4 +- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/JavaToCSharpCli/Program.cs b/JavaToCSharpCli/Program.cs index 8f029831..d74a0fc3 100644 --- a/JavaToCSharpCli/Program.cs +++ b/JavaToCSharpCli/Program.cs @@ -94,28 +94,26 @@ public static async Task Main(string[] args) { var rootCommand = new RootCommand("Java to C# Converter") { - Description = "A syntactic transformer of source code from Java to C#." + Description = "A syntactic transformer of source code from Java to C#.", }; - rootCommand.Add(CreateFileCommand()); - rootCommand.Add(CreateDirectoryCommand()); + rootCommand.Subcommands.Add(CreateFileCommand()); + rootCommand.Subcommands.Add(CreateDirectoryCommand()); - rootCommand.Add(_includeSubdirectoriesOption); - rootCommand.Add(_includeUsingsOption); - rootCommand.Add(_includeNamespaceOption); - rootCommand.Add(_includeCommentsOption); - rootCommand.Add(_useDebugAssertOption); - rootCommand.Add(_startInterfaceNamesWithIOption); - rootCommand.Add(_commentUnrecognizedCodeOption); - rootCommand.Add(_systemOutToConsoleOption); - rootCommand.Add(_fileScopedNamespacesOption); - rootCommand.Add(_clearDefaultUsingsOption); - rootCommand.Add(_addUsingsOption); - rootCommand.Add(_mappingsFileNameOption); + rootCommand.Options.Add(_includeSubdirectoriesOption); + rootCommand.Options.Add(_includeUsingsOption); + rootCommand.Options.Add(_includeNamespaceOption); + rootCommand.Options.Add(_includeCommentsOption); + rootCommand.Options.Add(_useDebugAssertOption); + rootCommand.Options.Add(_startInterfaceNamesWithIOption); + rootCommand.Options.Add(_commentUnrecognizedCodeOption); + rootCommand.Options.Add(_systemOutToConsoleOption); + rootCommand.Options.Add(_fileScopedNamespacesOption); + rootCommand.Options.Add(_clearDefaultUsingsOption); + rootCommand.Options.Add(_addUsingsOption); + rootCommand.Options.Add(_mappingsFileNameOption); - var parseResult = rootCommand.Parse(args); - - await parseResult.InvokeAsync(); + await rootCommand.Parse(args).InvokeAsync(); // flush logs _loggerFactory.Dispose(); @@ -258,13 +256,17 @@ private static void ConvertToCSharpDir(DirectoryInfo inputDirectory, DirectoryIn } } else + { _logger.LogError("Java input folder {path} doesn't exist!", inputDirectory); + } } private static void ConvertToCSharpFile(FileSystemInfo inputFile, FileSystemInfo? outputFile, JavaConversionOptions options, bool overwrite = true) { if (!overwrite && outputFile is { Exists: true }) + { _logger.LogInformation("{outputFilePath} exists, skip to next.", outputFile); + } else if (inputFile.Exists) { try @@ -302,7 +304,9 @@ private static void ConvertToCSharpFile(FileSystemInfo inputFile, FileSystemInfo } } else + { _logger.LogError("Java input file {filePath} doesn't exist!", inputFile.FullName); + } } private static void OutputFileOrPrint(string? fileName, string contents) diff --git a/JavaToCSharpGui/App.axaml b/JavaToCSharpGui/App.axaml index a8e8c4a5..29a53652 100644 --- a/JavaToCSharpGui/App.axaml +++ b/JavaToCSharpGui/App.axaml @@ -11,6 +11,6 @@ - + diff --git a/JavaToCSharpGui/Infrastructure/TextClipboard.cs b/JavaToCSharpGui/Infrastructure/TextClipboard.cs index 9cc8add4..3f5302d2 100644 --- a/JavaToCSharpGui/Infrastructure/TextClipboard.cs +++ b/JavaToCSharpGui/Infrastructure/TextClipboard.cs @@ -12,16 +12,18 @@ internal class TextClipboard(IClipboard? clipboard) : ITextClipboard { return null; } + return await clipboard.TryGetTextAsync(); } /// public async Task SetTextAsync(string? text) { - if(clipboard is null) + if (clipboard is null) { return; } + await clipboard.SetTextAsync(text); } }