From e9bc0ec7fc0f3455f116354e1d8e3792e0a8ad03 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 11 Feb 2011 22:54:18 +0100 Subject: [PATCH] Add simple output formatter. --- ICSharpCode.NRefactory.Demo/MainForm.cs | 5 +- ...OutputFormatter.cs => IOutputFormatter.cs} | 4 +- .../CSharp/OutputVisitor/OutputVisitor.cs | 64 ++++++++++++++----- .../TextWriterOutputFormatter.cs | 63 ++++++++++++++++++ .../ICSharpCode.NRefactory.csproj | 3 +- 5 files changed, 119 insertions(+), 20 deletions(-) rename ICSharpCode.NRefactory/CSharp/OutputVisitor/{OutputFormatter.cs => IOutputFormatter.cs} (87%) create mode 100644 ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs diff --git a/ICSharpCode.NRefactory.Demo/MainForm.cs b/ICSharpCode.NRefactory.Demo/MainForm.cs index 40bdeea98d..43627de732 100644 --- a/ICSharpCode.NRefactory.Demo/MainForm.cs +++ b/ICSharpCode.NRefactory.Demo/MainForm.cs @@ -125,7 +125,10 @@ namespace ICSharpCode.NRefactory.Demo void CSharpGenerateCodeButtonClick(object sender, EventArgs e) { - throw new NotImplementedException(); + StringWriter w = new StringWriter(); + OutputVisitor output = new OutputVisitor(w, new CSharpFormattingPolicy()); + compilationUnit.AcceptVisitor(output, null); + csharpCodeTextBox.Text = w.ToString(); } int GetOffset(TextBox textBox, AstLocation location) diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputFormatter.cs b/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs similarity index 87% rename from ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputFormatter.cs rename to ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs index 5c43bb3d32..6e4e458c1e 100644 --- a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputFormatter.cs +++ b/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs @@ -6,9 +6,9 @@ using System; namespace ICSharpCode.NRefactory.CSharp { /// - /// Output formatter for the output visitor. + /// Output formatter for the Output visitor. /// - public class OutputFormatter + public interface IOutputFormatter { void WriteIdentifier(string ident); void WriteKeyword(string keyword); diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index c638118243..91993857ad 100644 --- a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -5,9 +5,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; +using System.IO; using System.Linq; using System.Text; - using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.NRefactory.CSharp @@ -17,13 +17,24 @@ namespace ICSharpCode.NRefactory.CSharp /// public class OutputVisitor : AstVisitor { - readonly OutputFormatter formatter; + readonly IOutputFormatter formatter; readonly CSharpFormattingPolicy policy; AstNode currentContainerNode; readonly Stack positionStack = new Stack(); + char lastChar; - public OutputVisitor(OutputFormatter formatter, CSharpFormattingPolicy formattingPolicy) + public OutputVisitor(TextWriter textWriter, CSharpFormattingPolicy formattingPolicy) + { + if (textWriter == null) + throw new ArgumentNullException("textWriter"); + if (formattingPolicy == null) + throw new ArgumentNullException("formattingPolicy"); + this.formatter = new TextWriterOutputFormatter(textWriter); + this.policy = formattingPolicy; + } + + public OutputVisitor(IOutputFormatter formatter, CSharpFormattingPolicy formattingPolicy) { if (formatter == null) throw new ArgumentNullException("formatter"); @@ -119,7 +130,8 @@ namespace ICSharpCode.NRefactory.CSharp { WriteSpecialsUpToRole(AstNode.Roles.Comma, nextNode); Space(policy.SpacesBeforeComma); - formatter.WriteToken(","); + formatter.WriteToken(","); + lastChar = ','; Space(policy.SpacesAfterComma); } @@ -166,19 +178,26 @@ namespace ICSharpCode.NRefactory.CSharp void WriteKeyword(string keyword, Role tokenRole = null) { WriteSpecialsUpToRole(tokenRole ?? AstNode.Roles.Keyword); + if (lastChar == 'a') + Space(); formatter.WriteKeyword(keyword); + lastChar = 'a'; } void WriteIdentifier(string identifier, Role identifierRole = null) { WriteSpecialsUpToRole(identifierRole ?? AstNode.Roles.Identifier); + if (lastChar == 'a') + Space(); formatter.WriteIdentifier(identifier); + lastChar = 'a'; } void WriteToken(string token, Role tokenRole) { WriteSpecialsUpToRole(tokenRole); - formatter.WriteToken(token); + formatter.WriteToken(token); + lastChar = token[token.Length - 1]; } void LPar() @@ -198,7 +217,7 @@ namespace ICSharpCode.NRefactory.CSharp { if (!(currentContainerNode.Parent is ForStatement)) { WriteToken(";", AstNode.Roles.Semicolon); - formatter.NewLine(); + NewLine(); } } @@ -207,20 +226,30 @@ namespace ICSharpCode.NRefactory.CSharp /// void Space(bool addSpace = true) { - if (addSpace) + if (addSpace) { formatter.Space(); + lastChar = ' '; + } + } + + void NewLine() + { + formatter.NewLine(); + lastChar = '\n'; } void OpenBrace(BraceStyle style) { WriteSpecialsUpToRole(AstNode.Roles.LBrace); formatter.OpenBrace(); + lastChar = '{'; } void CloseBrace(BraceStyle style) { WriteSpecialsUpToRole(AstNode.Roles.RBrace); formatter.CloseBrace(); + lastChar = '}'; } #endregion @@ -262,6 +291,7 @@ namespace ICSharpCode.NRefactory.CSharp } WriteSpecialsUpToNode(ident); formatter.WriteIdentifier(ident.Name); + lastChar = 'a'; } } @@ -585,7 +615,8 @@ namespace ICSharpCode.NRefactory.CSharp public object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) { StartNode(primitiveExpression); - formatter.WriteToken(ToCSharpString(primitiveExpression)); + formatter.WriteToken(ToCSharpString(primitiveExpression)); + lastChar = 'a'; return EndNode(primitiveExpression); } @@ -785,7 +816,7 @@ namespace ICSharpCode.NRefactory.CSharp } WriteCommaSeparatedList(attributeSection.Attributes); WriteToken("]", AstNode.Roles.RBracket); - formatter.NewLine(); + NewLine(); return EndNode(attributeSection); } @@ -816,7 +847,7 @@ namespace ICSharpCode.NRefactory.CSharp foreach (var member in namespaceDeclaration.Members) member.AcceptVisitor(this, data); CloseBrace(policy.NamespaceBraceStyle); - formatter.NewLine(); + NewLine(); return EndNode(namespaceDeclaration); } @@ -860,7 +891,7 @@ namespace ICSharpCode.NRefactory.CSharp member.AcceptVisitor(this, data); } CloseBrace(braceStyle); - formatter.NewLine(); + NewLine(); return EndNode(typeDeclaration); } @@ -919,7 +950,7 @@ namespace ICSharpCode.NRefactory.CSharp node.AcceptVisitor(this, data); } CloseBrace(style); - formatter.NewLine(); + NewLine(); return EndNode(blockStatement); } @@ -1060,7 +1091,7 @@ namespace ICSharpCode.NRefactory.CSharp StartNode(labelStatement); WriteIdentifier(labelStatement.Label); WriteToken(":", LabelStatement.Roles.Colon); - formatter.NewLine(); + NewLine(); return EndNode(labelStatement); } @@ -1104,7 +1135,7 @@ namespace ICSharpCode.NRefactory.CSharp foreach (var section in switchStatement.SwitchSections) section.AcceptVisitor(this, data); CloseBrace(policy.StatementBraceStyle); - formatter.NewLine(); + NewLine(); return EndNode(switchStatement); } @@ -1125,7 +1156,7 @@ namespace ICSharpCode.NRefactory.CSharp Space(); caseLabel.Expression.AcceptVisitor(this, data); WriteToken(":", CaseLabel.Roles.Colon); - formatter.NewLine(); + NewLine(); return EndNode(caseLabel); } @@ -1557,7 +1588,8 @@ namespace ICSharpCode.NRefactory.CSharp WriteToken("[", ArraySpecifier.Roles.LBracket); foreach (var comma in arraySpecifier.GetChildrenByRole(ArraySpecifier.Roles.Comma)) { WriteSpecialsUpToNode(comma); - formatter.WriteToken(","); + formatter.WriteToken(","); + lastChar = ','; } WriteToken("]", ArraySpecifier.Roles.RBracket); return EndNode(arraySpecifier); diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs b/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs new file mode 100644 index 0000000000..f1f25345b6 --- /dev/null +++ b/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs @@ -0,0 +1,63 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Writes C# code into a TextWriter. + /// + public class TextWriterOutputFormatter : IOutputFormatter + { + readonly TextWriter textWriter; + + public TextWriterOutputFormatter(TextWriter textWriter) + { + if (textWriter == null) + throw new ArgumentNullException("textWriter"); + this.textWriter = textWriter; + } + + public void WriteIdentifier(string ident) + { + textWriter.Write(ident); + } + + public void WriteKeyword(string keyword) + { + textWriter.Write(keyword); + } + + public void WriteToken(string token) + { + textWriter.Write(token); + } + + public void Space() + { + textWriter.Write(' '); + } + + public void OpenBrace() + { + textWriter.Write('{'); + } + + public void CloseBrace() + { + textWriter.Write('}'); + } + + public void NewLine() + { + textWriter.WriteLine(); + } + + public void WriteComment(CommentType commentType, string content) + { + throw new NotImplementedException(); + } + } +} diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index d5300e6242..382eb33457 100644 --- a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -149,8 +149,9 @@ - + +