diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs index a4f448d2d..f91eba533 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs @@ -2417,6 +2417,36 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor EndNode(enumMemberDeclaration); } + public virtual void VisitExtensionDeclaration(ExtensionDeclaration extensionDeclaration) + { + StartNode(extensionDeclaration); + WriteAttributes(extensionDeclaration.Attributes); + WriteModifiers(extensionDeclaration.ModifierTokens); + WriteKeyword(ExtensionDeclaration.ExtensionKeywordRole); + WriteTypeParameters(extensionDeclaration.TypeParameters); + Space(policy.SpaceBeforeMethodDeclarationParentheses); + WriteCommaSeparatedListInParenthesis(extensionDeclaration.ReceiverParameters, policy.SpaceWithinMethodDeclarationParentheses); + foreach (Constraint constraint in extensionDeclaration.Constraints) + { + constraint.AcceptVisitor(this); + } + OpenBrace(policy.ClassBraceStyle); + bool first = true; + foreach (var member in extensionDeclaration.Members) + { + if (!first) + { + for (int i = 0; i < policy.MinimumBlankLinesBetweenMembers; i++) + NewLine(); + } + first = false; + member.AcceptVisitor(this); + } + CloseBrace(policy.ClassBraceStyle); + NewLine(); + EndNode(extensionDeclaration); + } + public virtual void VisitEventDeclaration(EventDeclaration eventDeclaration) { StartNode(eventDeclaration); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs b/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs index 2016b429c..5819b7277 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs @@ -157,6 +157,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax VisitChildren(enumMemberDeclaration); } + public virtual void VisitExtensionDeclaration(ExtensionDeclaration extensionDeclaration) + { + VisitChildren(extensionDeclaration); + } + public virtual void VisitUsingDeclaration(UsingDeclaration usingDeclaration) { VisitChildren(usingDeclaration); @@ -840,6 +845,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return VisitChildren(enumMemberDeclaration); } + public virtual T VisitExtensionDeclaration(ExtensionDeclaration extensionDeclaration) + { + return VisitChildren(extensionDeclaration); + } + public virtual T VisitUsingDeclaration(UsingDeclaration usingDeclaration) { return VisitChildren(usingDeclaration); @@ -1523,6 +1533,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return VisitChildren(enumMemberDeclaration, data); } + public virtual S VisitExtensionDeclaration(ExtensionDeclaration extensionDeclaration, T data) + { + return VisitChildren(extensionDeclaration, data); + } + public virtual S VisitUsingDeclaration(UsingDeclaration usingDeclaration, T data) { return VisitChildren(usingDeclaration, data); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/IAstVisitor.cs b/ICSharpCode.Decompiler/CSharp/Syntax/IAstVisitor.cs index 37dfd40a3..91bc63694 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/IAstVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/IAstVisitor.cs @@ -16,7 +16,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. - namespace ICSharpCode.Decompiler.CSharp.Syntax { /// @@ -136,6 +135,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax void VisitVariableInitializer(VariableInitializer variableInitializer); void VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration); void VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer); + void VisitExtensionDeclaration(ExtensionDeclaration extensionDeclaration); void VisitSyntaxTree(SyntaxTree syntaxTree); void VisitSimpleType(SimpleType simpleType); @@ -285,6 +285,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitVariableInitializer(VariableInitializer variableInitializer); S VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration); S VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer); + S VisitExtensionDeclaration(ExtensionDeclaration extensionDeclaration); S VisitSyntaxTree(SyntaxTree syntaxTree); S VisitSimpleType(SimpleType simpleType); @@ -434,6 +435,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitVariableInitializer(VariableInitializer variableInitializer, T data); S VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, T data); S VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer, T data); + S VisitExtensionDeclaration(ExtensionDeclaration extensionDeclaration, T data); S VisitSyntaxTree(SyntaxTree syntaxTree, T data); S VisitSimpleType(SimpleType simpleType, T data); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ExtensionDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ExtensionDeclaration.cs new file mode 100644 index 000000000..ad5c49839 --- /dev/null +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ExtensionDeclaration.cs @@ -0,0 +1,70 @@ +// Copyright (c) 2025 Siegfried Pammer +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using ICSharpCode.Decompiler.TypeSystem; + +namespace ICSharpCode.Decompiler.CSharp.Syntax +{ + public class ExtensionDeclaration : EntityDeclaration + { + public readonly static TokenRole ExtensionKeywordRole = new TokenRole("extension"); + + public override SymbolKind SymbolKind => throw new System.NotImplementedException(); + + public AstNodeCollection TypeParameters { + get { return GetChildrenByRole(Roles.TypeParameter); } + } + + public AstNodeCollection ReceiverParameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + + public AstNodeCollection Constraints { + get { return GetChildrenByRole(Roles.Constraint); } + } + + public AstNodeCollection Members { + get { return GetChildrenByRole(Roles.TypeMemberRole); } + } + + public ExtensionDeclaration() + { + } + + public override void AcceptVisitor(IAstVisitor visitor) + { + visitor.VisitExtensionDeclaration(this); + } + + public override T AcceptVisitor(IAstVisitor visitor) + { + return visitor.VisitExtensionDeclaration(this); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitExtensionDeclaration(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + var o = other as ExtensionDeclaration; + return o != null; + } + } +} diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 072043f0f..15d677535 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -104,6 +104,7 @@ + diff --git a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs index fe229607a..2361c8b9a 100644 --- a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs +++ b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs @@ -242,6 +242,7 @@ namespace ICSharpCode.ILSpy case "class": case "interface": case "delegate": + case "extension": color = referenceTypeKeywordsColor; break; case "record":