1- using JavaToCSharp ;
1+ using System . CommandLine ;
2+ using System . CommandLine . Invocation ;
3+ using JavaToCSharp ;
24using Microsoft . Extensions . Logging ;
35
46namespace JavaToCSharpCli ;
57
8+ /// <summary>
9+ /// The main JavaToCSharpCli program class.
10+ /// </summary>
611public class Program
712{
13+ private static readonly ILoggerFactory _loggerFactory ;
814 private static readonly ILogger _logger ;
915
16+ private static readonly Option < bool > _includeUsingsOption = new (
17+ name : "--include-usings" ,
18+ description : "Include using directives in output" ,
19+ getDefaultValue : ( ) => true ) ;
20+
21+ private static readonly Option < bool > _includeNamespaceOption = new (
22+ name : "--include-namespace" ,
23+ description : "Include namespace in output" ,
24+ getDefaultValue : ( ) => true ) ;
25+
26+ private static readonly Option < bool > _includeCommentsOption = new (
27+ name : "--include-comments" ,
28+ description : "Include comments in output" ,
29+ getDefaultValue : ( ) => true ) ;
30+
31+ private static readonly Option < bool > _useDebugAssertOption = new (
32+ name : "--use-debug-assert" ,
33+ description : "Use Debug.Assert for asserts" ,
34+ getDefaultValue : ( ) => false ) ;
35+
36+ private static readonly Option < bool > _startInterfaceNamesWithIOption = new (
37+ name : "--start-interface-names-with-i" ,
38+ description : "Prefix interface names with the letter I" ,
39+ getDefaultValue : ( ) => true ) ;
40+
41+ private static readonly Option < bool > _commentUnrecognizedCodeOption = new (
42+ name : "--comment-unrecognized-code" ,
43+ description : "Include unrecognized code in output as commented-out code" ,
44+ getDefaultValue : ( ) => true ) ;
45+
46+ private static readonly Option < bool > _systemOutToConsoleOption = new (
47+ name : "--system-out-to-console" ,
48+ description : "Convert System.out calls to Console" ,
49+ getDefaultValue : ( ) => false ) ;
50+
51+ private static readonly Option < bool > _clearDefaultUsingsOption = new (
52+ name : "--clear-usings" ,
53+ description : "Remove all default usings provided by this app" ,
54+ getDefaultValue : ( ) => false ) ;
55+
56+ private static readonly Option < List < string > > _addUsingsOption = new (
57+ name : "--add-using" ,
58+ description : "Adds a using directive to the collection of usings" )
59+ {
60+ ArgumentHelpName = "namespace"
61+ } ;
62+
1063 static Program ( )
1164 {
12- var loggerFactory =
13- LoggerFactory . Create ( builder => builder . AddSimpleConsole ( ) . SetMinimumLevel ( LogLevel . Information ) ) ;
14- _logger = loggerFactory . CreateLogger < Program > ( ) ;
65+ _loggerFactory = LoggerFactory . Create ( builder =>
66+ builder . AddSimpleConsole ( ) . SetMinimumLevel ( LogLevel . Information ) ) ;
67+ _logger = _loggerFactory . CreateLogger < Program > ( ) ;
1568 }
1669
17- public static void Main ( string [ ] args )
70+ public static async Task Main ( string [ ] args )
1871 {
19- try
72+ var rootCommand = new RootCommand ( "Java to C# Converter" )
2073 {
21- if ( args . Length < 3 )
22- ShowHelp ( ) ;
23- else
24- switch ( args [ 0 ] )
25- {
26- case "-f" :
27- ConvertToCSharpFile ( args [ 1 ] , args [ 2 ] ) ;
28- break ;
29- case "-d" :
30- ConvertToCSharpDir ( args [ 1 ] , args [ 2 ] ) ;
31- break ;
32- default :
33- ShowHelp ( ) ;
34- break ;
35- }
74+ Description = "A syntactic transformer of source code from Java to C#."
75+ } ;
76+
77+ rootCommand . AddCommand ( CreateFileCommand ( ) ) ;
78+ rootCommand . AddCommand ( CreateDirectoryCommand ( ) ) ;
79+
80+ rootCommand . AddGlobalOption ( _includeUsingsOption ) ;
81+ rootCommand . AddGlobalOption ( _includeNamespaceOption ) ;
82+ rootCommand . AddGlobalOption ( _includeCommentsOption ) ;
83+ rootCommand . AddGlobalOption ( _useDebugAssertOption ) ;
84+ rootCommand . AddGlobalOption ( _startInterfaceNamesWithIOption ) ;
85+ rootCommand . AddGlobalOption ( _commentUnrecognizedCodeOption ) ;
86+ rootCommand . AddGlobalOption ( _systemOutToConsoleOption ) ;
87+ rootCommand . AddGlobalOption ( _clearDefaultUsingsOption ) ;
88+ rootCommand . AddGlobalOption ( _addUsingsOption ) ;
89+
90+ await rootCommand . InvokeAsync ( args ) ;
91+
92+ // flush logs
93+ _loggerFactory . Dispose ( ) ;
94+ }
95+
96+ private static Command CreateFileCommand ( )
97+ {
98+ var inputArgument = new Argument < FileInfo > (
99+ name : "input" ,
100+ description : "A Java source code file to convert" ) ;
101+
102+ var outputArgument = new Argument < FileInfo ? > (
103+ name : "output" ,
104+ description : "Path to place the C# output file, or stdout if omitted" ,
105+ getDefaultValue : ( ) => null ) ;
106+
107+ var fileCommand = new Command ( "file" , "Convert a Java file to C#" ) ;
108+ fileCommand . AddArgument ( inputArgument ) ;
109+ fileCommand . AddArgument ( outputArgument ) ;
110+
111+ fileCommand . SetHandler ( context =>
112+ {
113+ var input = context . ParseResult . GetValueForArgument ( inputArgument ) ;
114+ var output = context . ParseResult . GetValueForArgument ( outputArgument ) ;
115+
116+ var options = GetJavaConversionOptions ( context ) ;
117+
118+ ConvertToCSharpFile ( input , output , options ) ;
119+ } ) ;
120+
121+ return fileCommand ;
122+ }
123+
124+ private static JavaConversionOptions GetJavaConversionOptions ( InvocationContext context )
125+ {
126+ var options = new JavaConversionOptions
127+ {
128+ IncludeUsings = context . ParseResult . GetValueForOption ( _includeUsingsOption ) ,
129+ IncludeComments = context . ParseResult . GetValueForOption ( _includeCommentsOption ) ,
130+ IncludeNamespace = context . ParseResult . GetValueForOption ( _includeNamespaceOption ) ,
131+ ConvertSystemOutToConsole = context . ParseResult . GetValueForOption ( _systemOutToConsoleOption ) ,
132+ StartInterfaceNamesWithI = context . ParseResult . GetValueForOption ( _startInterfaceNamesWithIOption ) ,
133+ UseDebugAssertForAsserts = context . ParseResult . GetValueForOption ( _useDebugAssertOption ) ,
134+ UseUnrecognizedCodeToComment = context . ParseResult . GetValueForOption ( _commentUnrecognizedCodeOption )
135+ } ;
136+
137+ if ( context . ParseResult . GetValueForOption ( _clearDefaultUsingsOption ) )
138+ {
139+ options . ClearUsings ( ) ;
36140 }
37- catch ( Exception ex )
141+
142+ foreach ( string ns in context . ParseResult . GetValueForOption ( _addUsingsOption ) ?? new List < string > ( ) )
38143 {
39- _logger . LogError ( ex , "Error: {Message}" , ex . Message ) ;
144+ options . AddUsing ( ns ) ;
40145 }
146+
147+ return options ;
148+ }
149+
150+ private static Command CreateDirectoryCommand ( )
151+ {
152+ var inputArgument = new Argument < DirectoryInfo > (
153+ name : "input" ,
154+ description : "A directory containing Java source code files to convert" ) ;
155+
156+ var outputArgument = new Argument < DirectoryInfo > (
157+ name : "output" ,
158+ description : "Path to place the C# output files" ) ;
159+
160+ var dirCommand = new Command ( "dir" , "Convert a directory containing Java files to C#" ) ;
161+ dirCommand . AddArgument ( inputArgument ) ;
162+ dirCommand . AddArgument ( outputArgument ) ;
41163
42- // allow logger background thread to flush
43- Thread . Sleep ( TimeSpan . FromSeconds ( 1 ) ) ;
164+ dirCommand . SetHandler ( context =>
165+ {
166+ var input = context . ParseResult . GetValueForArgument ( inputArgument ) ;
167+ var output = context . ParseResult . GetValueForArgument ( outputArgument ) ;
168+
169+ var options = GetJavaConversionOptions ( context ) ;
170+
171+ ConvertToCSharpDir ( input , output , options ) ;
172+ } ) ;
173+
174+ return dirCommand ;
44175 }
45176
46- private static void ConvertToCSharpDir ( string folderPath , string outputFolderPath )
177+ private static void ConvertToCSharpDir ( DirectoryInfo inputDirectory , DirectoryInfo outputDirectory , JavaConversionOptions options )
47178 {
48- if ( Directory . Exists ( folderPath ) )
179+ if ( inputDirectory . Exists )
49180 {
50- var input = new DirectoryInfo ( folderPath ) ;
51- foreach ( var f in input . GetFiles ( "*.java" , SearchOption . AllDirectories ) )
181+ foreach ( var f in inputDirectory . GetFiles ( "*.java" , SearchOption . AllDirectories ) )
52182 {
53183 string ? directoryName = f . DirectoryName ;
54184 if ( string . IsNullOrWhiteSpace ( directoryName ) )
55185 {
56186 continue ;
57187 }
58-
59- string newFolderPath = directoryName . Replace ( folderPath , outputFolderPath , StringComparison . OrdinalIgnoreCase ) ;
60- if ( ! Directory . Exists ( newFolderPath ) )
188+
189+ if ( ! outputDirectory . Exists )
61190 {
62- Directory . CreateDirectory ( newFolderPath ) ;
191+ outputDirectory . Create ( ) ;
63192 }
64193
65- ConvertToCSharpFile ( f . FullName ,
66- Path . Combine ( newFolderPath , Path . ChangeExtension ( f . Name , ".cs" ) ) ,
67- false ) ;
194+ ConvertToCSharpFile ( f ,
195+ new FileInfo ( Path . Combine ( outputDirectory . FullName , Path . ChangeExtension ( f . Name , ".cs" ) ) ) ,
196+ options ,
197+ false ) ;
68198 }
69199 }
70200 else
71- _logger . LogError ( "Java input folder {path} doesn't exist!" , folderPath ) ;
201+ _logger . LogError ( "Java input folder {path} doesn't exist!" , inputDirectory ) ;
72202 }
73203
74- private static void ConvertToCSharpFile ( string filePath , string outputFilePath , bool overwrite = true )
204+ private static void ConvertToCSharpFile ( FileSystemInfo inputFile , FileSystemInfo ? outputFile , JavaConversionOptions options , bool overwrite = true )
75205 {
76- if ( ! overwrite && File . Exists ( outputFilePath ) )
77- _logger . LogInformation ( "{outputFilePath} exists, skip to next." , outputFilePath ) ;
78- else if ( File . Exists ( filePath ) )
206+ if ( ! overwrite && outputFile is { Exists : true } )
207+ _logger . LogInformation ( "{outputFilePath} exists, skip to next." , outputFile ) ;
208+ else if ( inputFile . Exists )
79209 {
80210 try
81211 {
82- string javaText = File . ReadAllText ( filePath ) ;
83- var options = new JavaConversionOptions ( ) ;
212+ string javaText = File . ReadAllText ( inputFile . FullName ) ;
84213
85214 options . WarningEncountered += ( _ , eventArgs ) =>
86- {
87- _logger . LogWarning ( "Line {JavaLineNumber}: {Message}" , eventArgs . JavaLineNumber , eventArgs . Message ) ;
88- File . AppendAllText ( Path . ChangeExtension ( outputFilePath , ".warning" ) , eventArgs . Message + Environment . NewLine ) ;
89- } ;
215+ {
216+ if ( outputFile != null )
217+ {
218+ _logger . LogWarning ( "Line {JavaLineNumber}: {Message}" , eventArgs . JavaLineNumber ,
219+ eventArgs . Message ) ;
220+ }
221+
222+ OutputFileOrPrint ( outputFile != null ? Path . ChangeExtension ( outputFile . FullName , ".warning" ) : null ,
223+ eventArgs . Message + Environment . NewLine ) ;
224+ } ;
90225
91226 string ? parsed = JavaToCSharpConverter . ConvertText ( javaText , options ) ;
92- File . WriteAllText ( outputFilePath , parsed ) ;
93- _logger . LogInformation ( "{filePath} converted!" , filePath ) ;
227+ OutputFileOrPrint ( outputFile ? . FullName , parsed ?? string . Empty ) ;
228+
229+ if ( outputFile != null )
230+ {
231+ _logger . LogInformation ( "{filePath} converted!" , inputFile . Name ) ;
232+ }
94233 }
95234 catch ( Exception ex )
96235 {
97- _logger . LogError ( "{filePath} failed! {type}: {message}" , filePath , ex . GetType ( ) . Name , ex ) ;
98- File . WriteAllText ( Path . ChangeExtension ( outputFilePath , ".error" ) , ex . ToString ( ) ) ;
236+ _logger . LogError ( "{filePath} failed! {type}: {message}" , inputFile . Name , ex . GetType ( ) . Name , ex ) ;
237+
238+ if ( outputFile != null )
239+ {
240+ File . WriteAllText ( Path . ChangeExtension ( outputFile . FullName , ".error" ) , ex . ToString ( ) ) ;
241+ }
99242 }
100243 }
101244 else
102- _logger . LogError ( "Java input file {filePath} doesn't exist!" , filePath ) ;
245+ _logger . LogError ( "Java input file {filePath} doesn't exist!" , inputFile . FullName ) ;
103246 }
104247
105- private static void ShowHelp ( )
248+ private static void OutputFileOrPrint ( string ? fileName , string contents )
106249 {
107- Console . WriteLine ( "Usage:" ) ;
108- Console . WriteLine ( "\t JavaToCSharpCli.exe -f [pathToJavaFile] [pathToCsOutputFile]" ) ;
109- Console . WriteLine ( "\t JavaToCSharpCli.exe -d [pathToJavaFolder] [pathToCsOutputFolder]" ) ;
250+ if ( fileName == null )
251+ {
252+ Console . Out . WriteLine ( contents ) ;
253+ }
254+ else
255+ {
256+ File . WriteAllText ( fileName , contents ) ;
257+ }
110258 }
111259}
0 commit comments