-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Add support for C# 15 closed hierarchies #3869
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty | ||
| { | ||
| internal class ClosedHierarchies | ||
| { | ||
| public closed class Animal | ||
| { | ||
| public string Name { get; } | ||
|
|
||
| protected Animal() | ||
| { | ||
| Name = "unnamed"; | ||
| } | ||
|
|
||
| protected Animal(string name) | ||
| { | ||
| Name = name; | ||
| } | ||
| } | ||
|
|
||
| public class Cat : Animal | ||
| { | ||
| } | ||
|
|
||
| public sealed class Dog : Animal | ||
| { | ||
| public Dog() | ||
| : base("Dog") | ||
| { | ||
| } | ||
| } | ||
|
|
||
| public closed class Job | ||
| { | ||
| public required string Title { get; set; } | ||
| } | ||
|
|
||
| public sealed class CompileJob : Job | ||
| { | ||
| } | ||
|
|
||
| public closed class Tree<T> | ||
| { | ||
| } | ||
|
|
||
| public sealed class Leaf<U> : Tree<U> | ||
| { | ||
| } | ||
|
|
||
| public sealed class ArrayLeaf<V> : Tree<V[]> | ||
| { | ||
| } | ||
| } | ||
| public closed record JobStatus; | ||
| internal record JobStatusCanceled : JobStatus; | ||
| public record JobStatusQueued : JobStatus; | ||
| public record JobStatusRunning(int PercentComplete) : JobStatus; | ||
| internal closed class State | ||
| { | ||
| } | ||
| internal sealed class StateActive : State | ||
| { | ||
| } | ||
| } | ||
| #if !EXPECTED_OUTPUT | ||
| // The .NET 11 preview 5 BCL does not ship ClosedAttribute yet; the compiler requires | ||
| // every assembly using the 'closed' modifier to declare it (matched by full name). | ||
| namespace System.Runtime.CompilerServices | ||
| { | ||
| [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] | ||
| internal sealed class ClosedAttribute : Attribute | ||
| { | ||
| } | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| // #dependency ClosedHierarchiesCrossAssembly.dep.cs | ||
| using CrossAssemblyClosed; | ||
|
|
||
| namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty | ||
| { | ||
| public closed record LocalMessage; | ||
| public record LocalTextMessage(string Text) : LocalMessage; | ||
| public record Sedan(int Doors) : Car(Doors); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| namespace CrossAssemblyClosed | ||
| { | ||
| public closed record Vehicle; | ||
| public record Car(int Doors) : Vehicle; | ||
| public sealed record Truck(double PayloadTons) : Vehicle; | ||
| } | ||
|
|
||
| // Public so that the main test assembly can use the 'closed' modifier without | ||
| // declaring its own copy of the attribute (the shape the BCL will provide once | ||
| // ClosedAttribute ships). | ||
| namespace System.Runtime.CompilerServices | ||
| { | ||
| [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] | ||
| public sealed class ClosedAttribute : Attribute | ||
| { | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1703,6 +1703,12 @@ EntityDeclaration DoDecompile(ITypeDefinition typeDef, DecompileRun decompileRun | |
| { | ||
| RemoveAttribute(typeDecl, KnownAttribute.Required); | ||
| } | ||
| if (settings.ClosedHierarchies && RemoveAttribute(typeDecl, KnownAttribute.Closed)) | ||
| { | ||
| // closed classes are implicitly abstract | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If C# closed classes are implicitly abstract then we should only do this change for abstract classes; not for other classes that happen to have the attribute (because someone manually added it).
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. but yes, the pattern is: IsClosedTypeAttribute implies abstract
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CS8335 is only a C# compiler error; other languages can use that attribute however they like. |
||
| typeDecl.Modifiers |= Modifiers.Closed; | ||
| typeDecl.Modifiers &= ~Modifiers.Abstract; | ||
| } | ||
| if (typeDecl.ClassType == ClassType.Enum) | ||
| { | ||
| Debug.Assert(typeDef.Kind == TypeKind.Enum); | ||
|
|
@@ -2007,6 +2013,10 @@ EntityDeclaration DoDecompile(IMethod method, DecompileRun decompileRun, ITypeRe | |
| { | ||
| RemoveObsoleteAttribute(methodDecl, "Constructors of types with required members are not supported in this version of your compiler."); | ||
| } | ||
| if (method.IsConstructor && settings.ClosedHierarchies) | ||
| { | ||
| RemoveCompilerFeatureRequiredAttribute(methodDecl, "ClosedClasses"); | ||
| } | ||
| return methodDecl; | ||
|
|
||
| bool IsTypeHierarchyKnown(IType type) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -190,7 +190,10 @@ static void WriteDesktopExtensions(XmlTextWriter xml, ProjectType projectType) | |
|
|
||
| static void WriteProjectInfo(XmlTextWriter xml, IProjectInfoProvider project) | ||
| { | ||
| xml.WriteElementString("LangVersion", project.LanguageVersion.ToString().Replace("CSharp", "").Replace('_', '.')); | ||
| // C# 15 is still in preview; the compiler only accepts -langversion:preview for it. | ||
| xml.WriteElementString("LangVersion", project.LanguageVersion >= LanguageVersion.CSharp15_0 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should use "Preview" instead of the explicit version. Otherwise we will have to keep this updated. Preview and CSharp15_0 point to the same number as long as C# 15 is in preview. |
||
| ? "preview" | ||
| : project.LanguageVersion.ToString().Replace("CSharp", "").Replace('_', '.')); | ||
| xml.WriteElementString("AllowUnsafeBlocks", TrueString); | ||
| xml.WriteElementString("CheckForOverflowUnderflow", project.CheckForOverflowUnderflow ? TrueString : FalseString); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how is this related to the new language feature? A consequence of the Tester change?