From 3c638f6c43d77922e4a14c5af1b224e9563236f2 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 25 Nov 2016 18:02:14 +0100 Subject: Add 'ref T' AstType syntax node. This allows generating code for C# 7 'ref locals' and 'ref return'. --- ICSharpCode.NRefactory.CSharp/Ast/AstType.cs | 10 ++++++- ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs | 35 ++++++++++++++++++++-- .../OutputVisitor/CSharpOutputVisitor.cs | 3 ++ .../Refactoring/TypeSystemAstBuilder.cs | 9 +++++- .../Resolver/ResolveVisitor.cs | 3 ++ 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs b/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs index 2f13f0fd..80ca72ac 100644 --- a/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs @@ -209,7 +209,15 @@ namespace ICSharpCode.NRefactory.CSharp { return new ComposedType { BaseType = this, HasNullableSpecifier = true }; } - + + /// + /// Creates a C# 7 ref type from this type by nesting it in a . + /// + public virtual AstType MakeRefType() + { + return new ComposedType { BaseType = this, HasRefSpecifier = true }; + } + /// /// Builds an expression that can be used to access a static member on this type. /// diff --git a/ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs b/ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs index 0c0f96c6..2bbfc5a8 100644 --- a/ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs @@ -33,10 +33,25 @@ namespace ICSharpCode.NRefactory.CSharp { public class ComposedType : AstType { + public static readonly TokenRole RefRole = new TokenRole("ref"); public static readonly TokenRole NullableRole = new TokenRole("?"); public static readonly TokenRole PointerRole = new TokenRole("*"); public static readonly Role ArraySpecifierRole = new Role("ArraySpecifier"); - + + /// + /// Gets/sets whether this type has a 'ref' specifier. + /// This is used for C# 7 ref locals/ref return. + /// Parameters use ParameterDeclaration.ParameterModifier instead. + /// + public bool HasRefSpecifier { + get { + return !GetChildByRole(RefRole).IsNull; + } + set { + SetChildByRole(RefRole, value ? new CSharpTokenNode(TextLocation.Empty, null) : null); + } + } + public AstType BaseType { get { return GetChildByRole(Roles.Type); } set { SetChildByRole(Roles.Type, value); } @@ -102,7 +117,10 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ComposedType o = other as ComposedType; - return o != null && this.HasNullableSpecifier == o.HasNullableSpecifier && this.PointerRank == o.PointerRank + return o != null + && this.HasNullableSpecifier == o.HasNullableSpecifier + && this.PointerRank == o.PointerRank + && this.HasRefSpecifier == o.HasRefSpecifier && this.BaseType.DoMatch(o.BaseType, match) && this.ArraySpecifiers.DoMatch(o.ArraySpecifiers, match); } @@ -110,6 +128,8 @@ namespace ICSharpCode.NRefactory.CSharp public override string ToString(CSharpFormattingOptions formattingOptions) { StringBuilder b = new StringBuilder(); + if (this.HasRefSpecifier) + b.Append("ref "); b.Append(this.BaseType.ToString()); if (this.HasNullableSpecifier) b.Append('?'); @@ -137,7 +157,13 @@ namespace ICSharpCode.NRefactory.CSharp InsertChildBefore(this.ArraySpecifiers.FirstOrDefault(), new ArraySpecifier(dimensions), ArraySpecifierRole); return this; } - + + public override AstType MakeRefType() + { + this.HasRefSpecifier = true; + return this; + } + public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null) { if (interningProvider == null) @@ -153,6 +179,9 @@ namespace ICSharpCode.NRefactory.CSharp foreach (var a in this.ArraySpecifiers.Reverse()) { t = interningProvider.Intern(new ArrayTypeReference(t, a.Dimensions)); } + if (this.HasRefSpecifier) { + t = interningProvider.Intern(new ByReferenceTypeReference(t)); + } return t; } } diff --git a/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs index 769c4e09..683a632e 100644 --- a/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs @@ -2146,6 +2146,9 @@ namespace ICSharpCode.NRefactory.CSharp public virtual void VisitComposedType(ComposedType composedType) { StartNode(composedType); + if (composedType.HasRefSpecifier) { + WriteKeyword(ComposedType.RefRole); + } composedType.BaseType.AcceptVisitor(this); if (composedType.HasNullableSpecifier) { WriteToken(ComposedType.NullableRole); diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs index 5badd658..476ab8dc 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs @@ -217,6 +217,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring return ConvertType(typeWithElementType.ElementType).MakePointerType(); } else if (typeWithElementType is ArrayType) { return ConvertType(typeWithElementType.ElementType).MakeArrayType(((ArrayType)type).Dimensions); + } else if (typeWithElementType is ByReferenceType) { + return ConvertType(typeWithElementType.ElementType).MakeRefType(); } else { // e.g. ByReferenceType; not supported as type in C# return ConvertType(typeWithElementType.ElementType); @@ -584,7 +586,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (ShowAttributes) { decl.Attributes.AddRange (parameter.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); } - decl.Type = ConvertType(parameter.Type); + if (parameter.Type.Kind == TypeKind.ByReference) { + // avoid 'out ref' + decl.Type = ConvertType(((ByReferenceType)parameter.Type).ElementType); + } else { + decl.Type = ConvertType(parameter.Type); + } if (this.ShowParameterNames) { decl.Name = parameter.Name; } diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs index 340b290e..27a28660 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs @@ -3379,6 +3379,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver foreach (var a in composedType.ArraySpecifiers.Reverse()) { t = new ArrayType(resolver.Compilation, t, a.Dimensions); } + if (composedType.HasRefSpecifier) { + t = new ByReferenceType(t); + } return new TypeResolveResult(t); } #endregion -- cgit v1.2.3