From 43cf583e81d5ef9227e456ef6e3403b54455263f Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 12 May 2011 05:53:48 +0200 Subject: [PATCH] add MethodDeclaration, ConstructorDeclaration; EventMemberSpecifier, InterfaceMemberSpecifier for Handles and Implements clauses --- ICSharpCode.NRefactory.VB/Ast/AstNode.cs | 2 +- .../Ast/General/AttributedNode.cs | 2 +- .../Ast/General/EventMemberSpecifier.cs | 39 +++++ .../Ast/General/InterfaceMemberSpecifier.cs | 47 ++++++ .../Ast/TypeMembers/ConstructorDeclaration.cs | 40 ++++++ .../Ast/TypeMembers/MethodDeclaration.cs | 72 ++++++++++ ICSharpCode.NRefactory.VB/IAstVisitor.cs | 6 + .../ICSharpCode.NRefactory.VB.csproj | 5 + .../OutputVisitor/OutputVisitor.cs | 134 ++++++++++++++++-- .../Visitors/CSharpToVBConverterVisitor.cs | 76 +++++++++- 10 files changed, 403 insertions(+), 20 deletions(-) create mode 100644 ICSharpCode.NRefactory.VB/Ast/General/EventMemberSpecifier.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/General/InterfaceMemberSpecifier.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/TypeMembers/ConstructorDeclaration.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/TypeMembers/MethodDeclaration.cs diff --git a/ICSharpCode.NRefactory.VB/Ast/AstNode.cs b/ICSharpCode.NRefactory.VB/Ast/AstNode.cs index d66abad926..2d69dc3ec8 100644 --- a/ICSharpCode.NRefactory.VB/Ast/AstNode.cs +++ b/ICSharpCode.NRefactory.VB/Ast/AstNode.cs @@ -676,7 +676,7 @@ namespace ICSharpCode.NRefactory.VB public static readonly Role XmlIdentifier = new Role("XmlIdentifier", Ast.XmlIdentifier.Null); public static readonly Role XmlLiteralString = new Role("XmlLiteralString", Ast.XmlLiteralString.Null); -// public static readonly Role Body = new Role("Body", CSharp.BlockStatement.Null); + public static readonly Role Body = new Role("Body", Ast.BlockStatement.Null); public static readonly Role Parameter = new Role("Parameter"); public static readonly Role Argument = new Role("Argument", Ast.Expression.Null); public static readonly Role Type = new Role("Type", AstType.Null); diff --git a/ICSharpCode.NRefactory.VB/Ast/General/AttributedNode.cs b/ICSharpCode.NRefactory.VB/Ast/General/AttributedNode.cs index 37e364ee6b..160ab9145b 100644 --- a/ICSharpCode.NRefactory.VB/Ast/General/AttributedNode.cs +++ b/ICSharpCode.NRefactory.VB/Ast/General/AttributedNode.cs @@ -20,7 +20,7 @@ namespace ICSharpCode.NRefactory.VB.Ast set { SetModifiers(this, value); } } - public IEnumerable ModifierTokens { + public AstNodeCollection ModifierTokens { get { return GetChildrenByRole (ModifierRole); } } diff --git a/ICSharpCode.NRefactory.VB/Ast/General/EventMemberSpecifier.cs b/ICSharpCode.NRefactory.VB/Ast/General/EventMemberSpecifier.cs new file mode 100644 index 0000000000..5550ed53ae --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/General/EventMemberSpecifier.cs @@ -0,0 +1,39 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class EventMemberSpecifier : AstNode + { + public static readonly Role EventMemberSpecifierRole = new Role("EventMemberSpecifier"); + + public EventMemberSpecifier() + { + } + + public Expression Target { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public Identifier Member { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as EventMemberSpecifier; + return expr != null && + Target.DoMatch(expr.Target, match) && + Member.DoMatch(expr.Member, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitEventMemberSpecifier(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/General/InterfaceMemberSpecifier.cs b/ICSharpCode.NRefactory.VB/Ast/General/InterfaceMemberSpecifier.cs new file mode 100644 index 0000000000..1cf0610188 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/General/InterfaceMemberSpecifier.cs @@ -0,0 +1,47 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class InterfaceMemberSpecifier : AstNode + { + public static readonly Role InterfaceMemberSpecifierRole = new Role("InterfaceMemberSpecifier"); + + public InterfaceMemberSpecifier(Expression target, Identifier member) + { + Target = target; + Member = member; + } + + public InterfaceMemberSpecifier(AstType target, string member) + { + Target = new TypeReferenceExpression(target); + Member = new Identifier(member, AstLocation.Empty); + } + + public Expression Target { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public Identifier Member { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as InterfaceMemberSpecifier; + return expr != null && + Target.DoMatch(expr.Target, match) && + Member.DoMatch(expr.Member, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitInterfaceMemberSpecifier(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeMembers/ConstructorDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/ConstructorDeclaration.cs new file mode 100644 index 0000000000..e5a0b8a9fa --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/ConstructorDeclaration.cs @@ -0,0 +1,40 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Description of ConstructorDeclaration. + /// + public class ConstructorDeclaration : AttributedNode + { + public ConstructorDeclaration() + { + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var ctor = other as ConstructorDeclaration; + return ctor != null && + MatchAttributesAndModifiers(ctor, match) && + Parameters.DoMatch(ctor.Parameters, match) && + Body.DoMatch(ctor.Body, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitConstructorDeclaration(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeMembers/MethodDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/MethodDeclaration.cs new file mode 100644 index 0000000000..4cbe73da28 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/MethodDeclaration.cs @@ -0,0 +1,72 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class MethodDeclaration : AttributedNode + { + public MethodDeclaration() + { + } + + public bool IsSub { get; set; } + + public Identifier Name { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public AstNodeCollection TypeParameters { + get { return GetChildrenByRole(Roles.TypeParameter); } + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + + public AstNodeCollection ReturnTypeAttributes { + get { return GetChildrenByRole(AttributeBlock.ReturnTypeAttributeBlockRole); } + } + + public AstType ReturnType { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public AstNodeCollection HandlesClause { + get { return GetChildrenByRole(EventMemberSpecifier.EventMemberSpecifierRole); } + } + + public AstNodeCollection ImplementsClause { + get { return GetChildrenByRole(InterfaceMemberSpecifier.InterfaceMemberSpecifierRole); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var method = other as MethodDeclaration; + return method != null && + MatchAttributesAndModifiers(method, match) && + IsSub == method.IsSub && + Name.DoMatch(method.Name, match) && + TypeParameters.DoMatch(method.TypeParameters, match) && + Parameters.DoMatch(method.Parameters, match) && + ReturnTypeAttributes.DoMatch(method.ReturnTypeAttributes, match) && + ReturnType.DoMatch(method.ReturnType, match) && + HandlesClause.DoMatch(method.HandlesClause, match) && + ImplementsClause.DoMatch(method.ImplementsClause, match) && + Body.DoMatch(method.Body, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitMethodDeclaration(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/IAstVisitor.cs b/ICSharpCode.NRefactory.VB/IAstVisitor.cs index eba3749035..1b702c15af 100644 --- a/ICSharpCode.NRefactory.VB/IAstVisitor.cs +++ b/ICSharpCode.NRefactory.VB/IAstVisitor.cs @@ -14,6 +14,8 @@ namespace ICSharpCode.NRefactory.VB { S VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, T data); S VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, T data); S VisitVBTokenNode(VBTokenNode vBTokenNode, T data); + S VisitEventMemberSpecifier(EventMemberSpecifier eventMemberSpecifier, T data); + S VisitInterfaceMemberSpecifier(InterfaceMemberSpecifier interfaceMemberSpecifier, T data); // Global scope S VisitAliasImportsClause(AliasImportsClause aliasImportsClause, T data); @@ -29,6 +31,10 @@ namespace ICSharpCode.NRefactory.VB { S VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, T data); S VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, T data); + // TypeMember scope + S VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, T data); + S VisitMethodDeclaration(MethodDeclaration methodDeclaration, T data); + // Expression scope S VisitIdentifier(Identifier identifier, T data); S VisitXmlIdentifier(XmlIdentifier xmlIdentifier, T data); diff --git a/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj b/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj index c2c6c1dbff..d826ea8b5f 100644 --- a/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj +++ b/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj @@ -64,6 +64,8 @@ + + @@ -79,6 +81,8 @@ + + @@ -139,6 +143,7 @@ + diff --git a/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs index 4bba92a926..7e26773403 100644 --- a/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs @@ -87,7 +87,14 @@ namespace ICSharpCode.NRefactory.VB public object VisitVBTokenNode(VBTokenNode vBTokenNode, object data) { - throw new NotImplementedException(); + var mod = vBTokenNode as VBModifierToken; + if (mod != null) { + StartNode(vBTokenNode); + WriteKeyword(VBModifierToken.GetModifierName(mod.Modifier)); + return EndNode(vBTokenNode); + } else { + throw new NotSupportedException("Should never visit individual tokens"); + } } public object VisitAliasImportsClause(AliasImportsClause aliasImportsClause, object data) @@ -154,17 +161,7 @@ namespace ICSharpCode.NRefactory.VB node.AcceptVisitor(this, null); } NewLine(); - Indent(); - isFirst = true; - foreach (var member in namespaceDeclaration.Members) { - if (isFirst) { - isFirst = false; - } else { - NewLine(); - } - member.AcceptVisitor(this, data); - } - Unindent(); + WriteMembers(namespaceDeclaration.Members); WriteKeyword("End"); WriteKeyword("Namespace"); NewLine(); @@ -185,6 +182,8 @@ namespace ICSharpCode.NRefactory.VB WriteIdentifier(typeDeclaration.Name.Name); NewLine(); + WriteMembers(typeDeclaration.Members); + WriteKeyword("End"); WriteClassTypeKeyword(typeDeclaration); NewLine(); @@ -350,6 +349,84 @@ namespace ICSharpCode.NRefactory.VB return EndNode(typeReferenceExpression); } + public object VisitEventMemberSpecifier(EventMemberSpecifier eventMemberSpecifier, object data) + { + StartNode(eventMemberSpecifier); + + eventMemberSpecifier.Target.AcceptVisitor(this, data); + WriteToken(".", EventMemberSpecifier.Roles.Dot); + eventMemberSpecifier.Member.AcceptVisitor(this, data); + + return EndNode(eventMemberSpecifier); + } + + public object VisitInterfaceMemberSpecifier(InterfaceMemberSpecifier interfaceMemberSpecifier, object data) + { + StartNode(interfaceMemberSpecifier); + + interfaceMemberSpecifier.Target.AcceptVisitor(this, data); + WriteToken(".", EventMemberSpecifier.Roles.Dot); + interfaceMemberSpecifier.Member.AcceptVisitor(this, data); + + return EndNode(interfaceMemberSpecifier); + } + + #region TypeMembers + public object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) + { + StartNode(constructorDeclaration); + + WriteAttributes(constructorDeclaration.Attributes); + WriteModifiers(constructorDeclaration.ModifierTokens); + WriteKeyword("Sub"); + WriteKeyword("New"); + WriteCommaSeparatedListInParenthesis(constructorDeclaration.Parameters, false); + NewLine(); + + // TODO Body + + WriteKeyword("End"); + WriteKeyword("Sub"); + NewLine(); + + return EndNode(constructorDeclaration); + } + + public object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) + { + StartNode(methodDeclaration); + + WriteAttributes(methodDeclaration.Attributes); + WriteModifiers(methodDeclaration.ModifierTokens); + if (methodDeclaration.IsSub) + WriteKeyword("Sub"); + else + WriteKeyword("Function"); + methodDeclaration.Name.AcceptVisitor(this, data); + WriteTypeParameters(methodDeclaration.TypeParameters); + WriteCommaSeparatedListInParenthesis(methodDeclaration.Parameters, false); + if (!methodDeclaration.IsSub) { + WriteKeyword("As"); + WriteAttributes(methodDeclaration.ReturnTypeAttributes); + methodDeclaration.ReturnType.AcceptVisitor(this, data); + } + WriteHandlesClause(methodDeclaration.HandlesClause); + WriteImplementsClause(methodDeclaration.ImplementsClause); + NewLine(); + + // TODO Body + + WriteKeyword("End"); + if (methodDeclaration.IsSub) + WriteKeyword("Sub"); + else + WriteKeyword("Function"); + NewLine(); + + return EndNode(methodDeclaration); + } + #endregion + #region TypeName public object VisitPrimitiveType(PrimitiveType primitiveType, object data) { @@ -840,7 +917,7 @@ namespace ICSharpCode.NRefactory.VB embeddedStatement.AcceptVisitor(this, null); } - void WriteMethodBody(BlockStatement body) + void WriteBlock(BlockStatement body) { if (body.IsNull) NewLine(); @@ -848,6 +925,21 @@ namespace ICSharpCode.NRefactory.VB VisitBlockStatement(body, null); } + void WriteMembers(IEnumerable members) + { + Indent(); + bool isFirst = true; + foreach (var member in members) { + if (isFirst) { + isFirst = false; + } else { + NewLine(); + } + member.AcceptVisitor(this, null); + } + Unindent(); + } + void WriteAttributes(IEnumerable attributes) { foreach (AttributeBlock attr in attributes) { @@ -863,6 +955,22 @@ namespace ICSharpCode.NRefactory.VB } } + void WriteImplementsClause(AstNodeCollection implementsClause) + { + if (implementsClause.Any()) { + WriteKeyword("Implements"); + WriteCommaSeparatedList(implementsClause); + } + } + + void WriteHandlesClause(AstNodeCollection handlesClause) + { + if (handlesClause.Any()) { + WriteKeyword("Handles"); + WriteCommaSeparatedList(handlesClause); + } + } + void WritePrimitiveValue(object val) { if (val == null) { diff --git a/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs index 160f30ab2f..8c38d7ce8c 100644 --- a/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs +++ b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs @@ -301,6 +301,7 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitTypeDeclaration(CSharp.TypeDeclaration typeDeclaration, object data) { + // TODO add missing features! var type = new TypeDeclaration(); CSharp.Attribute stdModAttr; @@ -317,9 +318,12 @@ namespace ICSharpCode.NRefactory.VB.Visitors type.ClassType = typeDeclaration.ClassType; ConvertNodes(typeDeclaration.Attributes, type.Attributes); + ConvertNodes(typeDeclaration.ModifierTokens, type.ModifierTokens); type.Name = new Identifier(typeDeclaration.Name, AstLocation.Empty); + ConvertNodes(typeDeclaration.Members, type.Members); + return EndNode(typeDeclaration, type); } @@ -512,7 +516,13 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitConstructorDeclaration(CSharp.ConstructorDeclaration constructorDeclaration, object data) { - throw new NotImplementedException(); + var result = new ConstructorDeclaration(); + + ConvertNodes(constructorDeclaration.Attributes, result.Attributes); + ConvertNodes(constructorDeclaration.ModifierTokens, result.ModifierTokens); + ConvertNodes(constructorDeclaration.Parameters, result.Parameters); + + return EndNode(constructorDeclaration, result); } public AstNode VisitConstructorInitializer(CSharp.ConstructorInitializer constructorInitializer, object data) @@ -552,7 +562,28 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitMethodDeclaration(CSharp.MethodDeclaration methodDeclaration, object data) { - throw new NotImplementedException(); + var result = new MethodDeclaration(); + + ConvertNodes(methodDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), result.Attributes); + ConvertNodes(methodDeclaration.ModifierTokens, result.ModifierTokens); + result.Name = new Identifier(methodDeclaration.Name, AstLocation.Empty); + result.IsSub = IsSub(methodDeclaration.ReturnType); + ConvertNodes(methodDeclaration.Parameters, result.Parameters); + ConvertNodes(methodDeclaration.TypeParameters, result.TypeParameters); + ConvertNodes(methodDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), result.ReturnTypeAttributes); + result.ImplementsClause.Add( + new InterfaceMemberSpecifier((AstType)methodDeclaration.PrivateImplementationType.AcceptVisitor(this, data), + methodDeclaration.Name)); + if (!result.IsSub) + result.ReturnType = (AstType)methodDeclaration.ReturnType.AcceptVisitor(this, data); + + return EndNode(methodDeclaration, result); + } + + bool IsSub(CSharp.AstType returnType) + { + var t = returnType as CSharp.PrimitiveType; + return t != null && t.Keyword == "void"; } public AstNode VisitOperatorDeclaration(CSharp.OperatorDeclaration operatorDeclaration, object data) @@ -649,7 +680,39 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitCSharpTokenNode(CSharp.CSharpTokenNode cSharpTokenNode, object data) { - throw new NotImplementedException(); + var mod = cSharpTokenNode as CSharp.CSharpModifierToken; + if (mod != null) { + var convertedModifiers = ConvertModifiers(mod.Modifier, mod.Parent); + VBModifierToken token = null; + if (convertedModifiers != Modifiers.None) { + token = new VBModifierToken(AstLocation.Empty, convertedModifiers); + return EndNode(cSharpTokenNode, token); + } + return EndNode(cSharpTokenNode, token); + } else { + throw new NotSupportedException("Should never visit individual tokens"); + } + } + + Modifiers ConvertModifiers(CSharp.Modifiers modifier, CSharp.AstNode container) + { + if ((modifier & CSharp.Modifiers.Any) == CSharp.Modifiers.Any) + return Modifiers.Any; + + var mod = Modifiers.None; + + if ((modifier & CSharp.Modifiers.Const) == CSharp.Modifiers.Const) + mod |= Modifiers.Const; + if ((modifier & CSharp.Modifiers.Abstract) == CSharp.Modifiers.Abstract) { + if (container is CSharp.TypeDeclaration) + mod |= Modifiers.MustInherit; + else + mod |= Modifiers.MustOverride; + } + if ((modifier & CSharp.Modifiers.Static) == CSharp.Modifiers.Static) + mod |= Modifiers.Shared; + + return mod; } public AstNode VisitIdentifier(CSharp.Identifier identifier, object data) @@ -666,8 +729,11 @@ namespace ICSharpCode.NRefactory.VB.Visitors void ConvertNodes(IEnumerable nodes, VB.AstNodeCollection result) where T : VB.AstNode { - foreach (var node in nodes) - result.Add((T)node.AcceptVisitor(this, null)); + foreach (var node in nodes) { + T n = (T)node.AcceptVisitor(this, null); + if (n != null) + result.Add(n); + } } AstLocation ConvertLocation(CSharp.AstLocation location)