diff --git a/ILSpy/VB/VBLanguage.cs b/ILSpy/VB/VBLanguage.cs index 18f1dc449..c1b139d34 100644 --- a/ILSpy/VB/VBLanguage.cs +++ b/ILSpy/VB/VBLanguage.cs @@ -18,6 +18,8 @@ using System; using System.ComponentModel.Composition; +using System.Linq; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Ast; using ICSharpCode.Decompiler.Ast.Transforms; @@ -101,7 +103,7 @@ namespace ICSharpCode.ILSpy.VB astBuilder.RunTransformations(transformAbortCondition); if (options.DecompilerSettings.ShowXmlDocumentation) AddXmlDocTransform.Run(astBuilder.CompilationUnit); - var unit = astBuilder.CompilationUnit.AcceptVisitor(new CSharpToVBConverterVisitor(), null); + var unit = astBuilder.CompilationUnit.AcceptVisitor(new CSharpToVBConverterVisitor(new ILSpyEnvironmentProvider()), null); var outputFormatter = new VBTextOutputFormatter(output); var formattingPolicy = new VBFormattingOptions(); unit.AcceptVisitor(new OutputVisitor(outputFormatter, formattingPolicy), null); @@ -124,4 +126,21 @@ namespace ICSharpCode.ILSpy.VB }); } } + + public class ILSpyEnvironmentProvider : IEnvironmentProvider + { + public string RootNamespace { + get { + return ""; + } + } + + public string GetTypeNameForAttribute(ICSharpCode.NRefactory.CSharp.Attribute attribute) + { + return attribute.Type.Annotations + .OfType() + .First() + .FullName; + } + } } diff --git a/ILSpy/VB/VBTextOutputFormatter.cs b/ILSpy/VB/VBTextOutputFormatter.cs index 8fe0cfe11..5d8068d7e 100644 --- a/ILSpy/VB/VBTextOutputFormatter.cs +++ b/ILSpy/VB/VBTextOutputFormatter.cs @@ -1,5 +1,20 @@ -// 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) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// 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 System; using System.Collections.Generic; diff --git a/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs b/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs index 907e1a617..e16957fe8 100644 --- a/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; - using ICSharpCode.NRefactory.PatternMatching; using ICSharpCode.NRefactory.VB.Ast; @@ -95,12 +94,28 @@ namespace ICSharpCode.NRefactory.VB public object VisitAttribute(ICSharpCode.NRefactory.VB.Ast.Attribute attribute, object data) { - throw new NotImplementedException(); + StartNode(attribute); + + if (!attribute.Target.IsNull) { + attribute.Target.AcceptVisitor(this, data); + WriteToken(":", VB.Ast.Attribute.TargetRole); + } + attribute.Type.AcceptVisitor(this, data); + WriteCommaSeparatedListInParenthesis(attribute.Arguments, false); + + return EndNode(attribute); } public object VisitAttributeBlock(AttributeBlock attributeBlock, object data) { - throw new NotImplementedException(); + StartNode(attributeBlock); + + WriteToken("<", AttributeBlock.Roles.LChevron); + WriteCommaSeparatedList(attributeBlock.Attributes); + WriteToken(">", AttributeBlock.Roles.RChevron); + NewLine(); + + return EndNode(attributeBlock); } public object VisitImportsStatement(ImportsStatement importsStatement, object data) @@ -136,6 +151,17 @@ 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(); WriteKeyword("End"); WriteKeyword("Namespace"); NewLine(); @@ -149,7 +175,40 @@ namespace ICSharpCode.NRefactory.VB public object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) { - throw new NotImplementedException(); + StartNode(typeDeclaration); + WriteAttributes(typeDeclaration.Attributes); + WriteModifiers(typeDeclaration.ModifierTokens); + WriteClassTypeKeyword(typeDeclaration); + WriteIdentifier(typeDeclaration.Name.Name); + NewLine(); + + WriteKeyword("End"); + WriteClassTypeKeyword(typeDeclaration); + NewLine(); + return EndNode(typeDeclaration); + } + + void WriteClassTypeKeyword(TypeDeclaration typeDeclaration) + { + switch (typeDeclaration.ClassType) { + case ICSharpCode.NRefactory.TypeSystem.ClassType.Class: + WriteKeyword("Class"); + break; + case ICSharpCode.NRefactory.TypeSystem.ClassType.Enum: + break; + case ICSharpCode.NRefactory.TypeSystem.ClassType.Interface: + break; + case ICSharpCode.NRefactory.TypeSystem.ClassType.Struct: + WriteKeyword("Structure"); + break; + case ICSharpCode.NRefactory.TypeSystem.ClassType.Delegate: + break; + case ICSharpCode.NRefactory.TypeSystem.ClassType.Module: + WriteKeyword("Module"); + break; + default: + throw new Exception("Invalid value for ClassType"); + } } public object VisitXmlNamespaceImportsClause(XmlNamespaceImportsClause xmlNamespaceImportsClause, object data) @@ -362,7 +421,6 @@ namespace ICSharpCode.NRefactory.VB void Comma(AstNode nextNode, bool noSpaceAfterComma = false) { WriteSpecialsUpToRole(AstNode.Roles.Comma, nextNode); - Space(); // TODO: Comma policy has changed. formatter.WriteToken(","); lastWritten = LastWritten.Other; Space(!noSpaceAfterComma); // TODO: Comma policy has changed. @@ -577,6 +635,16 @@ namespace ICSharpCode.NRefactory.VB formatter.NewLine(); lastWritten = LastWritten.Whitespace; } + + void Indent() + { + formatter.Indent(); + } + + void Unindent() + { + formatter.Unindent(); + } #endregion #region IsKeyword Test diff --git a/NRefactory/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs b/NRefactory/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs index 0077ab687..4a3cc0609 100644 --- a/NRefactory/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs @@ -3,15 +3,31 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.VB.Ast; namespace ICSharpCode.NRefactory.VB.Visitors { + public interface IEnvironmentProvider + { + string RootNamespace { get; } + string GetTypeNameForAttribute(CSharp.Attribute attribute); + } + /// /// Description of CSharpToVBConverterVisitor. /// public class CSharpToVBConverterVisitor : CSharp.IAstVisitor { + IEnvironmentProvider provider; + + public CSharpToVBConverterVisitor(IEnvironmentProvider provider) + { + this.provider = provider; + } + public AstNode VisitAnonymousMethodExpression(CSharp.AnonymousMethodExpression anonymousMethodExpression, object data) { throw new NotImplementedException(); @@ -234,12 +250,21 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitAttribute(CSharp.Attribute attribute, object data) { - throw new NotImplementedException(); + var attr = new VB.Ast.Attribute(); + + // TODO : attribute targets + + attr.Type = (AstType)attribute.Type.AcceptVisitor(this, data); +// ConvertNodes(attribute.Arguments, attr.Arguments); + + return EndNode(attribute, attr); } public AstNode VisitAttributeSection(CSharp.AttributeSection attributeSection, object data) { - throw new NotImplementedException(); + AttributeBlock block = new AttributeBlock(); + ConvertNodes(attributeSection.Attributes, block.Attributes); + return EndNode(attributeSection, block); } public AstNode VisitDelegateDeclaration(CSharp.DelegateDeclaration delegateDeclaration, object data) @@ -261,6 +286,23 @@ namespace ICSharpCode.NRefactory.VB.Visitors { var type = new TypeDeclaration(); + CSharp.Attribute stdModAttr; + + if (typeDeclaration.ClassType == ClassType.Class && HasAttribute(typeDeclaration.Attributes, "Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute", out stdModAttr)) { + type.ClassType = ClassType.Module; + // remove AttributeSection if only one attribute is present + var attrSec = (CSharp.AttributeSection)stdModAttr.Parent; + if (attrSec.Attributes.Count == 1) + attrSec.Remove(); + else + stdModAttr.Remove(); + } else + type.ClassType = typeDeclaration.ClassType; + + ConvertNodes(typeDeclaration.Attributes, type.Attributes); + + type.Name = new Identifier(typeDeclaration.Name, AstLocation.Empty); + return EndNode(typeDeclaration, type); } @@ -620,5 +662,17 @@ namespace ICSharpCode.NRefactory.VB.Visitors { return result; } + + bool HasAttribute(CSharp.AstNodeCollection attributes, string name, out CSharp.Attribute foundAttribute) + { + foreach (var attr in attributes.SelectMany(a => a.Attributes)) { + if (provider.GetTypeNameForAttribute(attr) == name) { + foundAttribute = attr; + return true; + } + } + foundAttribute = null; + return false; + } } }