How CS2J Works
CS2J operates in two phases. Phase 1 creates a translation repository for the application. The repository maps all the types (classes, enums, and so on) used by the application to translation templates. Phase 2 converts each C# file to Java classes, using the translation repository to accurately convert the C# source to Java code.
Building the Translation Repository
The translation repository defines how external
references from a fragment of the C# application should be
translated. As an example, the correct translation of
objRef.Member++ depends on whether
Member is a field or a property of
External references recorded in the environment can have many types: classes, structs, delegates, fields, properties, events, and so on. They refer to types in:
- the C# application being translated,
- the .NET Framework, and
- third party libraries.
CS2J builds the repository by scanning all the C# files in the C# application. It then adds entries for .NET Framework and third party libraries from a set of XML translation files. CS2J comes with a set of translation files for the most commonly used .NET Framework classes and it is straightforward for clients to add or modify these files to improve the translation of their application.
Translating to Java
Each C# file is converted to Java code.
A C# 4.0 conformant front end parses the source code into an abstract syntax tree. The parser includes a pre-processor so compiler and conditional compilation directives are respected.
The C# syntax tree is then transformed into a set of Java-like syntax trees, each representing one top level type from the original source file (in C# a file may contain many types, but in Java each top level type must be written to its own file). During this stage we are converting as much C# syntax to Java syntax as we can, e.g. properties and indexers are rewritten as getter and setter methods, structs are rewritten as classes, and so on.
Each of the Java syntax trees is then further converted using the
translation repository to fix up external references. During this phase we infer
types for the expressions in the tree so that the translations can
take into account the types of component expressions. These types
also allow us to carry out type based syntactical transformations
(so we can replace
var str = "Hello
String str = "Hello
Finally the fully translated Java syntax trees are pretty printed to Java source files.