You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Review and correct the Java-to-C# type mappings (#134) (#181)
Fixes#134.
## Interfaces were bound to concrete types
The issue's example — `Map<K, V>` mapping to `Dictionary<K, V>` instead
of `IDictionary<K, V>` — turned out to be one of several. Converting a
probe file showed variables declared against a Java collection interface
were losing the abstraction the Java source chose, even though `List` →
`IList` was already correct.
`Map` now maps to `IDictionary` and `Set` to `ISet`, with `Collection`,
`Comparable`, `Comparator`, `Iterable`, `SortedMap`/`SortedSet` and the
`Navigable` variants mapped alongside them.
## ...which required mapping the concrete types too
Fixing only the interfaces would have made output *worse*, since
interfaces are exactly what you cannot instantiate. `new HashMap<>()`
was previously emitting `new HashMap()` — a type that does not exist in
.NET — because `HashMap`, `LinkedHashMap`, `LinkedHashSet`, `TreeMap`
and `TreeSet` had no entries at all. Those are added.
`Map.put` is also lowered to an index assignment, the way `List.set`
already was. This is not strictly a type mapping, but the integration
test would not compile without it: a converted `IDictionary` had no
usable way to store into itself. It reuses the existing `List.set`
lowering, which already discards the same return value.
## Other commonly-used types filled in
Boxed primitives (`Character`, `Double`, `Short`, and `Byte` → `sbyte`,
as Java's `byte` is signed), `BigDecimal`, `StringBuffer`, `Closeable`,
and the common exceptions: `Throwable`, `ClassCastException`,
`NumberFormatException`, `IndexOutOfBoundsException`,
`ArrayIndexOutOfBoundsException`, `NoSuchElementException`,
`OutOfMemoryError`, `StackOverflowError`, `InterruptedException`,
`CloneNotSupportedException`.
## Deliberately left unmapped: `CharSequence`, `Runnable`, `Void`
All three were added and then removed. `CharSequence` → `string` broke
an existing test: `class Foo implements CharSequence` became `: string`,
which does not compile because `string` is sealed. `Runnable` → `Action`
and `Void` → `void` (illegal in `Future<Void>`) fail the same way.
The mapping table is position-blind — it cannot tell a variable
declaration from a base-type list — so each of these would fix some
conversions while breaking others. Handling them needs position-aware
conversion rather than a table entry.
## Testing
All 415 tests pass. New unit tests cover the collection, simple-type and
exception mappings; a new `CollectionTypeMappings.java` integration
resource compiles and *runs* the generated C# rather than only asserting
on the conversion text. To support that, the integration harness now
mirrors the CLI's default usings and references `System.Collections.dll`
(where `SortedDictionary`/`SortedSet` live).
## Pre-existing bugs found but not fixed
Both are out of scope here; happy to file them separately.
- **Diamond operator drops type arguments**: `new HashMap<>()` converts
to `new Dictionary()`, losing `<string, int>`. The new test resource
uses explicit type arguments to work around this.
- **Qualified type names pass through unconverted**: `TypeNameParser`
handles simple identifiers only, so `Map.Entry<K, V>` is left as-is.
Relatedly, `java.*` imports emit unusable usings such as `using Java;`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
0 commit comments