Skip to content

Support Java 17 sealed classes (#66) - #166

Merged
paulirwin merged 1 commit into
masterfrom
issue/66-sealed-classes
Aug 16, 2026
Merged

Support Java 17 sealed classes (#66)#166
paulirwin merged 1 commit into
masterfrom
issue/66-sealed-classes

Conversation

@paulirwin

Copy link
Copy Markdown
Owner

Fixes #66.

Translates Java sealed, permits, and non-sealed as far as C# allows.

Behavior

Java C# output Warning
sealed class (option on, default) public closed class Shape no
sealed class (option off) public class Shape yes
sealed interface public interface Service yes
non-sealed class public class Square : Shape yes

In every case a comment recording the original hierarchy is emitted above the type, so the permits clause is not lost:

// Java: sealed, permits Circle, Square, Rectangle
public closed class Shape
{
}

Sealed interfaces have no C# equivalent at all, so they always warn. non-sealed re-opens a hierarchy that C# never closed in the first place, so it emits no modifier and warns.

Option

New JavaConversionOptions.UseClosedForSealedClasses, enabled by default, controls whether sealed classes get the C# 15 closed modifier (which requires .NET 11). It is exposed as --no-closed-for-sealed-classes on the CLI and as a checkbox in the GUI settings window.

Notes for review

  • Roslyn has no ClosedKeyword token yet, so closed is emitted via SyntaxFactory.ParseToken. Verified it survives NormalizeWhitespace().
  • The Java17SealedClasses.java fixture is registered under GeneralSuccessfulConversionTest rather than FullIntegrationTests, because the latter compiles the output with Roslyn and closed will not parse until the toolchain supports C# 15. Worth moving once it does.
  • Records cannot be sealed in Java, but a sealed interface permitting records is the canonical pattern. The interface side is covered here; adding the // Java: comment to permitted records in RecordDeclarationVisitor would be a follow-up.

Testing

New ConvertSealedTests.cs covers all four cases above plus the no-permits and non-sealed-type paths. Full suite passes (318 tests); solution builds clean.

🤖 Generated with Claude Code

Translates Java `sealed`, `permits`, and `non-sealed` as far as C# allows:

- Sealed classes gain the C# 15 `closed` modifier, controlled by the new
  `UseClosedForSealedClasses` option (enabled by default). When disabled,
  the modifier is omitted and a warning is raised instead.
- Sealed interfaces have no C# equivalent, so they are emitted as plain
  interfaces with a warning.
- `non-sealed` classes are emitted without a modifier, with a warning.

In all cases a `// Java: sealed, permits X, Y` comment is added above the
type so the original hierarchy is not lost.

The option is exposed on the CLI as `--no-closed-for-sealed-classes` and
as a checkbox in the GUI settings window.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@paulirwin
paulirwin marked this pull request as ready for review August 16, 2026 20:49
@paulirwin
paulirwin merged commit b400707 into master Aug 16, 2026
5 checks passed
@paulirwin
paulirwin deleted the issue/66-sealed-classes branch August 16, 2026 20:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Java 17 Sealed Classes

1 participant