Browse Source

move all formatting to CSharpOutputVisitor, move all "extra" work to decorating ITokenWriter

newNRILSpyDebugger
Siegfried Pammer 13 years ago
parent
commit
61614a56e3
  1. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpInsightItem.cs
  2. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/SegmentTrackingOutputFormatter.cs
  3. 6
      src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs
  4. 9
      src/Libraries/ICSharpCode.Decompiler/Ast/AstBuilder.cs
  5. 25
      src/Libraries/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs
  6. 4
      src/Libraries/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
  7. 12
      src/Libraries/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  8. 1
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  9. 154
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs
  10. 762
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs
  11. 183
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs
  12. 250
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/TextWriterOutputFormatter.cs
  13. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs
  14. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpUnresolvedFile.cs
  15. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CSharpOutputVisitorTests.cs
  16. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpInsightItem.cs

@ -63,7 +63,7 @@ namespace CSharpBinding.Completion @@ -63,7 +63,7 @@ namespace CSharpBinding.Completion
get { return null; }
}
sealed class ParameterHighlightingOutputFormatter : TextWriterOutputFormatter
sealed class ParameterHighlightingOutputFormatter : TextWriterTokenWriter
{
StringBuilder b;
int highlightedParameterIndex;

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/SegmentTrackingOutputFormatter.cs

@ -15,7 +15,7 @@ namespace CSharpBinding.Completion @@ -15,7 +15,7 @@ namespace CSharpBinding.Completion
/// <summary>
/// Output formatter that creates a dictionary from AST nodes to segments in the output text.
/// </summary>
public class SegmentTrackingOutputFormatter : TextWriterOutputFormatter
public class SegmentTrackingOutputFormatter : TextWriterTokenWriter
{
Dictionary<AstNode, ISegment> segments = new Dictionary<AstNode, ISegment>();
Stack<int> startOffsets = new Stack<int>();

6
src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs

@ -424,11 +424,11 @@ namespace Debugger.AddIn @@ -424,11 +424,11 @@ namespace Debugger.AddIn
sb.Append("}");
return sb.ToString();
} else if (val.Type.IsKnownType(KnownTypeCode.Char)) {
return "'" + CSharpOutputVisitor.ConvertChar((char)val.PrimitiveValue) + "'";
return "'" + TextWriterTokenWriter.ConvertChar((char)val.PrimitiveValue) + "'";
} else if (val.Type.IsKnownType(KnownTypeCode.String)) {
return "\"" + CSharpOutputVisitor.ConvertString((string)val.PrimitiveValue) + "\"";
return "\"" + TextWriterTokenWriter.ConvertString((string)val.PrimitiveValue) + "\"";
} else if (val.Type.IsPrimitiveType()) {
return CSharpOutputVisitor.PrintPrimitiveValue(val.PrimitiveValue);
return TextWriterTokenWriter.PrintPrimitiveValue(val.PrimitiveValue);
} else {
return val.InvokeToString(evalThread);
}

9
src/Libraries/ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -150,6 +150,13 @@ namespace ICSharpCode.Decompiler.Ast @@ -150,6 +150,13 @@ namespace ICSharpCode.Decompiler.Ast
get { return syntaxTree; }
}
/// <summary>
/// Gets the context used by this AstBuilder.
/// </summary>
public DecompilerContext Context {
get { return context; }
}
/// <summary>
/// Generates C# code from the abstract source tree.
/// </summary>
@ -160,7 +167,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -160,7 +167,7 @@ namespace ICSharpCode.Decompiler.Ast
RunTransformations();
syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
var outputFormatter = new TextOutputFormatter(output) { FoldBraces = context.Settings.FoldBraces };
var outputFormatter = new TextTokenWriter(output) { FoldBraces = context.Settings.FoldBraces };
var formattingPolicy = context.Settings.CSharpFormattingOptions;
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(outputFormatter, formattingPolicy));
}

25
src/Libraries/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs

@ -27,7 +27,7 @@ using Mono.Cecil; @@ -27,7 +27,7 @@ using Mono.Cecil;
namespace ICSharpCode.Decompiler.Ast
{
public class TextOutputFormatter : IOutputFormatter
public class TextTokenWriter : ITokenWriter
{
readonly ITextOutput output;
readonly Stack<AstNode> nodeStack = new Stack<AstNode>();
@ -40,37 +40,37 @@ namespace ICSharpCode.Decompiler.Ast @@ -40,37 +40,37 @@ namespace ICSharpCode.Decompiler.Ast
public bool FoldBraces = false;
public TextOutputFormatter(ITextOutput output)
public TextTokenWriter(ITextOutput output)
{
if (output == null)
throw new ArgumentNullException("output");
this.output = output;
}
public void WriteIdentifier(string identifier)
public void WriteIdentifier(Identifier identifier)
{
var definition = GetCurrentDefinition();
if (definition != null) {
output.WriteDefinition(identifier, definition, false);
output.WriteDefinition(identifier.Name, definition, false);
return;
}
object memberRef = GetCurrentMemberReference();
if (memberRef != null) {
output.WriteReference(identifier, memberRef);
output.WriteReference(identifier.Name, memberRef);
return;
}
definition = GetCurrentLocalDefinition();
if (definition != null) {
output.WriteDefinition(identifier, definition);
output.WriteDefinition(identifier.Name, definition);
return;
}
memberRef = GetCurrentLocalReference();
if (memberRef != null) {
output.WriteReference(identifier, memberRef, true);
output.WriteReference(identifier.Name, memberRef, true);
return;
}
@ -79,7 +79,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -79,7 +79,7 @@ namespace ICSharpCode.Decompiler.Ast
firstUsingDeclaration = false;
}
output.Write(identifier);
output.Write(identifier.Name);
}
MemberReference GetCurrentMemberReference()
@ -160,12 +160,12 @@ namespace ICSharpCode.Decompiler.Ast @@ -160,12 +160,12 @@ namespace ICSharpCode.Decompiler.Ast
return null;
}
public void WriteKeyword(string keyword)
public void WriteKeyword(Role role, string keyword)
{
output.Write(keyword);
}
public void WriteToken(string token)
public void WriteToken(Role role, string token)
{
// Attach member reference to token only if there's no identifier in the current node.
MemberReference memberRef = GetCurrentMemberReference();
@ -267,6 +267,11 @@ namespace ICSharpCode.Decompiler.Ast @@ -267,6 +267,11 @@ namespace ICSharpCode.Decompiler.Ast
output.WriteLine();
}
public void WritePrimitiveValue(object value)
{
}
Stack<TextLocation> startLocations = new Stack<TextLocation>();
Stack<MethodDebugSymbols> symbolsStack = new Stack<MethodDebugSymbols>();

4
src/Libraries/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs

@ -222,7 +222,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -222,7 +222,7 @@ namespace ICSharpCode.Decompiler.Disassembler
} else {
// The ECMA specification says that ' inside SQString should be ecaped using an octal escape sequence,
// but we follow Microsoft's ILDasm and use \'.
return "'" + NRefactory.CSharp.CSharpOutputVisitor.ConvertString(identifier).Replace("'", "\\'") + "'";
return "'" + NRefactory.CSharp.TextWriterTokenWriter.ConvertString(identifier).Replace("'", "\\'") + "'";
}
}
@ -353,7 +353,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -353,7 +353,7 @@ namespace ICSharpCode.Decompiler.Disassembler
string s = operand as string;
if (s != null) {
writer.Write("\"" + NRefactory.CSharp.CSharpOutputVisitor.ConvertString(s) + "\"");
writer.Write("\"" + NRefactory.CSharp.TextWriterTokenWriter.ConvertString(s) + "\"");
} else if (operand is char) {
writer.Write(((int)(char)operand).ToString());
} else if (operand is float) {

12
src/Libraries/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -126,10 +126,10 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -126,10 +126,10 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write("pinvokeimpl");
if (method.HasPInvokeInfo && method.PInvokeInfo != null) {
PInvokeInfo info = method.PInvokeInfo;
output.Write("(\"" + NRefactory.CSharp.CSharpOutputVisitor.ConvertString(info.Module.Name) + "\"");
output.Write("(\"" + NRefactory.CSharp.TextWriterTokenWriter.ConvertString(info.Module.Name) + "\"");
if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != method.Name)
output.Write(" as \"" + NRefactory.CSharp.CSharpOutputVisitor.ConvertString(info.EntryPoint) + "\"");
output.Write(" as \"" + NRefactory.CSharp.TextWriterTokenWriter.ConvertString(info.EntryPoint) + "\"");
if (info.IsNoMangle)
output.Write(" nomangle");
@ -346,7 +346,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -346,7 +346,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(" = ");
if (na.Argument.Value is string) {
// secdecls use special syntax for strings
output.Write("string('{0}')", NRefactory.CSharp.CSharpOutputVisitor.ConvertString((string)na.Argument.Value).Replace("'", "\'"));
output.Write("string('{0}')", NRefactory.CSharp.TextWriterTokenWriter.ConvertString((string)na.Argument.Value).Replace("'", "\'"));
} else {
WriteConstant(na.Argument.Value);
}
@ -574,10 +574,10 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -574,10 +574,10 @@ namespace ICSharpCode.Decompiler.Disassembler
if (cmi == null)
goto default;
output.Write("custom(\"{0}\", \"{1}\"",
NRefactory.CSharp.CSharpOutputVisitor.ConvertString(cmi.ManagedType.FullName),
NRefactory.CSharp.CSharpOutputVisitor.ConvertString(cmi.Cookie));
NRefactory.CSharp.TextWriterTokenWriter.ConvertString(cmi.ManagedType.FullName),
NRefactory.CSharp.TextWriterTokenWriter.ConvertString(cmi.Cookie));
if (cmi.Guid != Guid.Empty || !string.IsNullOrEmpty(cmi.UnmanagedType)) {
output.Write(", \"{0}\", \"{1}\"", cmi.Guid.ToString(), NRefactory.CSharp.CSharpOutputVisitor.ConvertString(cmi.UnmanagedType));
output.Write(", \"{0}\", \"{1}\"", cmi.Guid.ToString(), NRefactory.CSharp.TextWriterTokenWriter.ConvertString(cmi.UnmanagedType));
}
output.Write(')');
break;

1
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -208,6 +208,7 @@ @@ -208,6 +208,7 @@
<Compile Include="OutputVisitor\CodeDomConvertVisitor.cs" />
<Compile Include="OutputVisitor\CSharpAmbience.cs" />
<Compile Include="OutputVisitor\InsertParenthesesVisitor.cs" />
<Compile Include="OutputVisitor\InsertRequiredSpacesDecorator.cs" />
<Compile Include="OutputVisitor\IOutputFormatter.cs" />
<Compile Include="OutputVisitor\CSharpOutputVisitor.cs" />
<Compile Include="OutputVisitor\TextWriterOutputFormatter.cs" />

154
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs

@ -37,98 +37,98 @@ namespace ICSharpCode.NRefactory.CSharp @@ -37,98 +37,98 @@ namespace ICSharpCode.NRefactory.CSharp
throw new ArgumentNullException("entity");
StringWriter writer = new StringWriter();
ConvertEntity(entity, new TextWriterOutputFormatter(writer), FormattingOptionsFactory.CreateMono ());
ConvertEntity(entity, new TextWriterTokenWriter(writer), FormattingOptionsFactory.CreateMono ());
return writer.ToString();
}
public void ConvertEntity(IEntity entity, IOutputFormatter formatter, CSharpFormattingOptions formattingPolicy)
public void ConvertEntity(IEntity entity, ITokenWriter writer, CSharpFormattingOptions formattingPolicy)
{
if (entity == null)
throw new ArgumentNullException("entity");
if (formatter == null)
throw new ArgumentNullException("formatter");
if (writer == null)
throw new ArgumentNullException("writer");
if (formattingPolicy == null)
throw new ArgumentNullException("options");
TypeSystemAstBuilder astBuilder = CreateAstBuilder();
EntityDeclaration node = astBuilder.ConvertEntity(entity);
PrintModifiers(node.Modifiers, formatter);
PrintModifiers(node.Modifiers, writer);
if ((ConversionFlags & ConversionFlags.ShowDefinitionKeyword) == ConversionFlags.ShowDefinitionKeyword) {
if (node is TypeDeclaration) {
switch (((TypeDeclaration)node).ClassType) {
case ClassType.Class:
formatter.WriteKeyword("class");
writer.WriteKeyword(Roles.ClassKeyword, "class");
break;
case ClassType.Struct:
formatter.WriteKeyword("struct");
writer.WriteKeyword(Roles.StructKeyword, "struct");
break;
case ClassType.Interface:
formatter.WriteKeyword("interface");
writer.WriteKeyword(Roles.InterfaceKeyword, "interface");
break;
case ClassType.Enum:
formatter.WriteKeyword("enum");
writer.WriteKeyword(Roles.EnumKeyword, "enum");
break;
default:
throw new Exception("Invalid value for ClassType");
}
formatter.Space();
writer.Space();
} else if (node is DelegateDeclaration) {
formatter.WriteKeyword("delegate");
formatter.Space();
writer.WriteKeyword(Roles.DelegateKeyword, "delegate");
writer.Space();
} else if (node is EventDeclaration) {
formatter.WriteKeyword("event");
formatter.Space();
writer.WriteKeyword(EventDeclaration.EventKeywordRole, "event");
writer.Space();
}
}
if ((ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType) {
var rt = node.GetChildByRole(Roles.Type);
if (!rt.IsNull) {
rt.AcceptVisitor(new CSharpOutputVisitor(formatter, formattingPolicy));
formatter.Space();
rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
writer.Space();
}
}
if (entity is ITypeDefinition)
WriteTypeDeclarationName((ITypeDefinition)entity, formatter, formattingPolicy);
WriteTypeDeclarationName((ITypeDefinition)entity, writer, formattingPolicy);
else
WriteMemberDeclarationName((IMember)entity, formatter, formattingPolicy);
WriteMemberDeclarationName((IMember)entity, writer, formattingPolicy);
if ((ConversionFlags & ConversionFlags.ShowParameterList) == ConversionFlags.ShowParameterList && HasParameters(entity)) {
formatter.WriteToken(entity.SymbolKind == SymbolKind.Indexer ? "[" : "(");
writer.WriteToken(entity.SymbolKind == SymbolKind.Indexer ? Roles.LBracket : Roles.LPar, entity.SymbolKind == SymbolKind.Indexer ? "[" : "(");
bool first = true;
foreach (var param in node.GetChildrenByRole(Roles.Parameter)) {
if (first) {
first = false;
} else {
formatter.WriteToken(",");
formatter.Space();
writer.WriteToken(Roles.Comma, ",");
writer.Space();
}
param.AcceptVisitor(new CSharpOutputVisitor(formatter, formattingPolicy));
param.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
}
formatter.WriteToken(entity.SymbolKind == SymbolKind.Indexer ? "]" : ")");
writer.WriteToken(entity.SymbolKind == SymbolKind.Indexer ? Roles.RBracket : Roles.RPar, entity.SymbolKind == SymbolKind.Indexer ? "]" : ")");
}
if ((ConversionFlags & ConversionFlags.ShowBody) == ConversionFlags.ShowBody && !(node is TypeDeclaration)) {
IProperty property = entity as IProperty;
if (property != null) {
formatter.Space();
formatter.WriteToken("{");
formatter.Space();
writer.Space();
writer.WriteToken(Roles.LBrace, "{");
writer.Space();
if (property.CanGet) {
formatter.WriteKeyword("get");
formatter.WriteToken(";");
formatter.Space();
writer.WriteKeyword(PropertyDeclaration.GetKeywordRole, "get");
writer.WriteToken(Roles.Semicolon, ";");
writer.Space();
}
if (property.CanSet) {
formatter.WriteKeyword("set");
formatter.WriteToken(";");
formatter.Space();
writer.WriteKeyword(PropertyDeclaration.SetKeywordRole, "set");
writer.WriteToken(Roles.Semicolon, ";");
writer.Space();
}
formatter.WriteToken("}");
writer.WriteToken(Roles.RBrace, "}");
} else {
formatter.WriteToken(";");
writer.WriteToken(Roles.Semicolon, ";");
}
}
}
@ -160,87 +160,97 @@ namespace ICSharpCode.NRefactory.CSharp @@ -160,87 +160,97 @@ namespace ICSharpCode.NRefactory.CSharp
return astBuilder;
}
void WriteTypeDeclarationName(ITypeDefinition typeDef, IOutputFormatter formatter, CSharpFormattingOptions formattingPolicy)
void WriteTypeDeclarationName(ITypeDefinition typeDef, ITokenWriter writer, CSharpFormattingOptions formattingPolicy)
{
TypeSystemAstBuilder astBuilder = CreateAstBuilder();
TypeDeclaration node = (TypeDeclaration)astBuilder.ConvertEntity(typeDef);
if (typeDef.DeclaringTypeDefinition != null) {
WriteTypeDeclarationName(typeDef.DeclaringTypeDefinition, formatter, formattingPolicy);
formatter.WriteToken(".");
WriteTypeDeclarationName(typeDef.DeclaringTypeDefinition, writer, formattingPolicy);
writer.WriteToken(Roles.Dot, ".");
} else if ((ConversionFlags & ConversionFlags.UseFullyQualifiedTypeNames) == ConversionFlags.UseFullyQualifiedTypeNames) {
formatter.WriteIdentifier(typeDef.Namespace);
formatter.WriteToken(".");
WriteQualifiedName(typeDef.Namespace, writer, formattingPolicy);
writer.WriteToken(Roles.Dot, ".");
}
formatter.WriteIdentifier(typeDef.Name);
writer.WriteIdentifier(node.NameToken);
if ((ConversionFlags & ConversionFlags.ShowTypeParameterList) == ConversionFlags.ShowTypeParameterList) {
var outputVisitor = new CSharpOutputVisitor(formatter, formattingPolicy);
outputVisitor.WriteTypeParameters(astBuilder.ConvertEntity(typeDef).GetChildrenByRole(Roles.TypeParameter));
var outputVisitor = new CSharpOutputVisitor(writer, formattingPolicy);
outputVisitor.WriteTypeParameters(node.GetChildrenByRole(Roles.TypeParameter));
}
}
void WriteMemberDeclarationName(IMember member, IOutputFormatter formatter, CSharpFormattingOptions formattingPolicy)
void WriteMemberDeclarationName(IMember member, ITokenWriter writer, CSharpFormattingOptions formattingPolicy)
{
TypeSystemAstBuilder astBuilder = CreateAstBuilder();
EntityDeclaration node = astBuilder.ConvertEntity(member);
TypeDeclaration typeDecl = (TypeDeclaration)astBuilder.ConvertEntity(member.DeclaringTypeDefinition);
if ((ConversionFlags & ConversionFlags.ShowDeclaringType) == ConversionFlags.ShowDeclaringType) {
ConvertType(member.DeclaringType, formatter, formattingPolicy);
formatter.WriteToken(".");
ConvertType(member.DeclaringType, writer, formattingPolicy);
writer.WriteToken(Roles.Dot, ".");
}
switch (member.SymbolKind) {
case SymbolKind.Indexer:
formatter.WriteKeyword("this");
writer.WriteKeyword(Roles.Identifier, "this");
break;
case SymbolKind.Constructor:
formatter.WriteIdentifier(member.DeclaringType.Name);
WriteQualifiedName(member.DeclaringType.Name, writer, formattingPolicy);
break;
case SymbolKind.Destructor:
formatter.WriteToken("~");
formatter.WriteIdentifier(member.DeclaringType.Name);
writer.WriteToken(DestructorDeclaration.TildeRole, "~");
WriteQualifiedName(member.DeclaringType.Name, writer, formattingPolicy);
break;
case SymbolKind.Operator:
switch (member.Name) {
case "op_Implicit":
formatter.WriteKeyword("implicit");
formatter.Space();
formatter.WriteKeyword("operator");
formatter.Space();
ConvertType(member.ReturnType, formatter, formattingPolicy);
writer.WriteKeyword(OperatorDeclaration.ImplicitRole, "implicit");
writer.Space();
writer.WriteKeyword(OperatorDeclaration.OperatorKeywordRole, "operator");
writer.Space();
ConvertType(member.ReturnType, writer, formattingPolicy);
break;
case "op_Explicit":
formatter.WriteKeyword("explicit");
formatter.Space();
formatter.WriteKeyword("operator");
formatter.Space();
ConvertType(member.ReturnType, formatter, formattingPolicy);
writer.WriteKeyword(OperatorDeclaration.ExplicitRole, "explicit");
writer.Space();
writer.WriteKeyword(OperatorDeclaration.OperatorKeywordRole, "operator");
writer.Space();
ConvertType(member.ReturnType, writer, formattingPolicy);
break;
default:
formatter.WriteKeyword("operator");
formatter.Space();
writer.WriteKeyword(OperatorDeclaration.OperatorKeywordRole, "operator");
writer.Space();
var operatorType = OperatorDeclaration.GetOperatorType(member.Name);
if (operatorType.HasValue)
formatter.WriteToken(OperatorDeclaration.GetToken(operatorType.Value));
writer.WriteToken(OperatorDeclaration.GetRole(operatorType.Value), OperatorDeclaration.GetToken(operatorType.Value));
else
formatter.WriteIdentifier(member.Name);
writer.WriteIdentifier(node.NameToken);
break;
}
break;
default:
formatter.WriteIdentifier(member.Name);
writer.WriteIdentifier(node.NameToken);
break;
}
if ((ConversionFlags & ConversionFlags.ShowTypeParameterList) == ConversionFlags.ShowTypeParameterList && member.SymbolKind == SymbolKind.Method) {
var outputVisitor = new CSharpOutputVisitor(formatter, formattingPolicy);
outputVisitor.WriteTypeParameters(astBuilder.ConvertEntity(member).GetChildrenByRole(Roles.TypeParameter));
var outputVisitor = new CSharpOutputVisitor(writer, formattingPolicy);
outputVisitor.WriteTypeParameters(node.GetChildrenByRole(Roles.TypeParameter));
}
}
void PrintModifiers(Modifiers modifiers, IOutputFormatter formatter)
void PrintModifiers(Modifiers modifiers, ITokenWriter writer)
{
foreach (var m in CSharpModifierToken.AllModifiers) {
if ((modifiers & m) == m) {
formatter.WriteKeyword(CSharpModifierToken.GetModifierName(m));
formatter.Space();
writer.WriteKeyword(EntityDeclaration.ModifierRole, CSharpModifierToken.GetModifierName(m));
writer.Space();
}
}
}
void WriteQualifiedName(string name, ITokenWriter writer, CSharpFormattingOptions formattingPolicy)
{
var node = AstType.Create(name);
var outputVisitor = new CSharpOutputVisitor(writer, formattingPolicy);
node.AcceptVisitor(outputVisitor);
}
#endregion
public string ConvertVariable(IVariable v)
@ -260,16 +270,16 @@ namespace ICSharpCode.NRefactory.CSharp @@ -260,16 +270,16 @@ namespace ICSharpCode.NRefactory.CSharp
return astType.ToString();
}
public void ConvertType(IType type, IOutputFormatter formatter, CSharpFormattingOptions formattingPolicy)
public void ConvertType(IType type, ITokenWriter writer, CSharpFormattingOptions formattingPolicy)
{
TypeSystemAstBuilder astBuilder = CreateAstBuilder();
AstType astType = astBuilder.ConvertType(type);
astType.AcceptVisitor(new CSharpOutputVisitor(formatter, formattingPolicy));
astType.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
}
public string ConvertConstantValue(object constantValue)
{
return CSharpOutputVisitor.PrintPrimitiveValue(constantValue);
return TextWriterTokenWriter.PrintPrimitiveValue(constantValue);
}
public string WrapComment(string comment)

762
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs

File diff suppressed because it is too large Load Diff

183
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs

@ -0,0 +1,183 @@ @@ -0,0 +1,183 @@
// Copyright (c) 2010-2013 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;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.NRefactory.PatternMatching;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.NRefactory.CSharp
{
class InsertRequiredSpacesDecorator : DecoratingTokenWriter
{
/// <summary>
/// Used to insert the minimal amount of spaces so that the lexer recognizes the tokens that were written.
/// </summary>
LastWritten lastWritten;
enum LastWritten
{
Whitespace,
Other,
KeywordOrIdentifier,
Plus,
Minus,
Ampersand,
QuestionMark,
Division
}
public InsertRequiredSpacesDecorator(ITokenWriter writer)
: base(writer)
{
}
public override void WriteIdentifier(Identifier identifier)
{
if (identifier.IsVerbatim) {
if (lastWritten == LastWritten.KeywordOrIdentifier) {
// this space is not strictly required, so we call Space()
Space();
}
} else if (lastWritten == LastWritten.KeywordOrIdentifier) {
// this space is strictly required, so we directly call the formatter
base.Space();
}
base.WriteIdentifier(identifier);
lastWritten = LastWritten.KeywordOrIdentifier;
}
public override void WriteKeyword(Role role, string keyword)
{
if (lastWritten == LastWritten.KeywordOrIdentifier) {
Space();
}
base.WriteKeyword(role, keyword);
lastWritten = LastWritten.KeywordOrIdentifier;
}
public override void WriteToken(Role role, string token)
{
// Avoid that two +, - or ? tokens are combined into a ++, -- or ?? token.
// Note that we don't need to handle tokens like = because there's no valid
// C# program that contains the single token twice in a row.
// (for +, - and &, this can happen with unary operators;
// for ?, this can happen in "a is int? ? b : c" or "a as int? ?? 0";
// and for /, this can happen with "1/ *ptr" or "1/ //comment".)
if (lastWritten == LastWritten.Plus && token[0] == '+' ||
lastWritten == LastWritten.Minus && token[0] == '-' ||
lastWritten == LastWritten.Ampersand && token[0] == '&' ||
lastWritten == LastWritten.QuestionMark && token[0] == '?' ||
lastWritten == LastWritten.Division && token[0] == '*') {
base.Space();
}
base.WriteToken(role, token);
if (token == "+") {
lastWritten = LastWritten.Plus;
} else if (token == "-") {
lastWritten = LastWritten.Minus;
} else if (token == "&") {
lastWritten = LastWritten.Ampersand;
} else if (token == "?") {
lastWritten = LastWritten.QuestionMark;
} else if (token == "/") {
lastWritten = LastWritten.Division;
} else {
lastWritten = LastWritten.Other;
}
}
public override void Space()
{
base.Space();
lastWritten = LastWritten.Whitespace;
}
public void Indent()
{
throw new NotImplementedException();
}
public void Unindent()
{
throw new NotImplementedException();
}
public override void NewLine()
{
base.NewLine();
lastWritten = LastWritten.Whitespace;
}
public override void WriteComment(CommentType commentType, string content)
{
if (lastWritten == LastWritten.Division) {
// When there's a comment starting after a division operator
// "1.0 / /*comment*/a", then we need to insert a space in front of the comment.
base.Space();
}
base.WriteComment(commentType, content);
lastWritten = LastWritten.Whitespace;
}
public override void WritePreProcessorDirective(PreProcessorDirectiveType type, string argument)
{
base.WritePreProcessorDirective(type, argument);
lastWritten = LastWritten.Whitespace;
}
public override void WritePrimitiveValue(object value)
{
base.WritePrimitiveValue(value);
if (value == null || value is bool)
return;
if (value is string) {
lastWritten = LastWritten.Other;
} else if (value is char) {
lastWritten = LastWritten.Other;
} else if (value is decimal) {
lastWritten = LastWritten.Other;
} else if (value is float) {
float f = (float)value;
if (float.IsInfinity(f) || float.IsNaN(f)) return;
lastWritten = LastWritten.Other;
} else if (value is double) {
double f = (double)value;
if (double.IsInfinity(f) || double.IsNaN(f)) return;
// needs space if identifier follows number;
// this avoids mistaking the following identifier as type suffix
lastWritten = LastWritten.KeywordOrIdentifier;
} else if (value is IFormattable) {
// needs space if identifier follows number;
// this avoids mistaking the following identifier as type suffix
lastWritten = LastWritten.KeywordOrIdentifier;
} else {
lastWritten = LastWritten.Other;
}
}
}
}

250
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/TextWriterOutputFormatter.cs

@ -17,14 +17,16 @@ @@ -17,14 +17,16 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Globalization;
using System.IO;
using System.Text;
namespace ICSharpCode.NRefactory.CSharp
{
/// <summary>
/// Writes C# code into a TextWriter.
/// </summary>
public class TextWriterOutputFormatter : IOutputFormatter
public class TextWriterTokenWriter : ITokenWriter
{
readonly TextWriter textWriter;
int indentation;
@ -42,7 +44,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -42,7 +44,7 @@ namespace ICSharpCode.NRefactory.CSharp
public string IndentationString { get; set; }
public TextWriterOutputFormatter(TextWriter textWriter)
public TextWriterTokenWriter(TextWriter textWriter)
{
if (textWriter == null)
throw new ArgumentNullException("textWriter");
@ -50,21 +52,23 @@ namespace ICSharpCode.NRefactory.CSharp @@ -50,21 +52,23 @@ namespace ICSharpCode.NRefactory.CSharp
this.IndentationString = "\t";
}
public void WriteIdentifier(string ident)
public void WriteIdentifier(Identifier identifier)
{
WriteIndentation();
textWriter.Write(ident);
if (identifier.IsVerbatim)
textWriter.Write('@');
textWriter.Write(identifier.Name);
isAtStartOfLine = false;
}
public void WriteKeyword(string keyword)
public void WriteKeyword(Role role, string keyword)
{
WriteIndentation();
textWriter.Write(keyword);
isAtStartOfLine = false;
}
public void WriteToken(string token)
public void WriteToken(Role role, string token)
{
WriteIndentation();
textWriter.Write(token);
@ -77,79 +81,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -77,79 +81,6 @@ namespace ICSharpCode.NRefactory.CSharp
textWriter.Write(' ');
}
public void OpenBrace(BraceStyle style)
{
switch (style) {
case BraceStyle.DoNotChange:
case BraceStyle.EndOfLine:
case BraceStyle.BannerStyle:
WriteIndentation();
if (!isAtStartOfLine)
textWriter.Write(' ');
textWriter.Write('{');
break;
case BraceStyle.EndOfLineWithoutSpace:
WriteIndentation();
textWriter.Write('{');
break;
case BraceStyle.NextLine:
if (!isAtStartOfLine)
NewLine();
WriteIndentation();
textWriter.Write('{');
break;
case BraceStyle.NextLineShifted:
NewLine ();
Indent();
WriteIndentation();
textWriter.Write('{');
NewLine();
return;
case BraceStyle.NextLineShifted2:
NewLine ();
Indent();
WriteIndentation();
textWriter.Write('{');
break;
default:
throw new ArgumentOutOfRangeException ();
}
Indent();
NewLine();
}
public void CloseBrace(BraceStyle style)
{
switch (style) {
case BraceStyle.DoNotChange:
case BraceStyle.EndOfLine:
case BraceStyle.EndOfLineWithoutSpace:
case BraceStyle.NextLine:
Unindent();
WriteIndentation();
textWriter.Write('}');
isAtStartOfLine = false;
break;
case BraceStyle.BannerStyle:
case BraceStyle.NextLineShifted:
WriteIndentation();
textWriter.Write('}');
isAtStartOfLine = false;
Unindent();
break;
case BraceStyle.NextLineShifted2:
Unindent();
WriteIndentation();
textWriter.Write('}');
isAtStartOfLine = false;
Unindent();
break;
default:
throw new ArgumentOutOfRangeException ();
}
}
protected void WriteIndentation()
{
if (needsIndent) {
@ -220,6 +151,167 @@ namespace ICSharpCode.NRefactory.CSharp @@ -220,6 +151,167 @@ namespace ICSharpCode.NRefactory.CSharp
NewLine();
}
public static string PrintPrimitiveValue(object value)
{
TextWriter writer = new StringWriter();
TextWriterTokenWriter tokenWriter = new TextWriterTokenWriter(writer);
tokenWriter.WritePrimitiveValue(value);
return writer.ToString();
}
public void WritePrimitiveValue(object value)
{
if (value == null) {
// usually NullReferenceExpression should be used for this, but we'll handle it anyways
textWriter.Write("null");
return;
}
if (value is bool) {
if ((bool)value) {
textWriter.Write("true");
} else {
textWriter.Write("false");
}
return;
}
if (value is string) {
textWriter.Write("\"" + ConvertString(value.ToString()) + "\"");
} else if (value is char) {
textWriter.Write("'" + ConvertCharLiteral((char)value) + "'");
} else if (value is decimal) {
textWriter.Write(((decimal)value).ToString(NumberFormatInfo.InvariantInfo) + "m");
} else if (value is float) {
float f = (float)value;
if (float.IsInfinity(f) || float.IsNaN(f)) {
// Strictly speaking, these aren't PrimitiveExpressions;
// but we still support writing these to make life easier for code generators.
textWriter.Write("float");
WriteToken(Roles.Dot, ".");
if (float.IsPositiveInfinity(f)) {
textWriter.Write("PositiveInfinity");
} else if (float.IsNegativeInfinity(f)) {
textWriter.Write("NegativeInfinity");
} else {
textWriter.Write("NaN");
}
return;
}
if (f == 0 && 1 / f == float.NegativeInfinity) {
// negative zero is a special case
// (again, not a primitive expression, but it's better to handle
// the special case here than to do it in all code generators)
textWriter.Write("-");
}
textWriter.Write(f.ToString("R", NumberFormatInfo.InvariantInfo) + "f");
} else if (value is double) {
double f = (double)value;
if (double.IsInfinity(f) || double.IsNaN(f)) {
// Strictly speaking, these aren't PrimitiveExpressions;
// but we still support writing these to make life easier for code generators.
textWriter.Write("double");
textWriter.Write(".");
if (double.IsPositiveInfinity(f)) {
textWriter.Write("PositiveInfinity");
} else if (double.IsNegativeInfinity(f)) {
textWriter.Write("NegativeInfinity");
} else {
textWriter.Write("NaN");
}
return;
}
if (f == 0 && 1 / f == double.NegativeInfinity) {
// negative zero is a special case
// (again, not a primitive expression, but it's better to handle
// the special case here than to do it in all code generators)
textWriter.Write("-");
}
string number = f.ToString("R", NumberFormatInfo.InvariantInfo);
if (number.IndexOf('.') < 0 && number.IndexOf('E') < 0) {
number += ".0";
}
textWriter.Write(number);
} else if (value is IFormattable) {
StringBuilder b = new StringBuilder ();
// if (primitiveExpression.LiteralFormat == LiteralFormat.HexadecimalNumber) {
// b.Append("0x");
// b.Append(((IFormattable)val).ToString("x", NumberFormatInfo.InvariantInfo));
// } else {
b.Append(((IFormattable)value).ToString(null, NumberFormatInfo.InvariantInfo));
// }
if (value is uint || value is ulong) {
b.Append("u");
}
if (value is long || value is ulong) {
b.Append("L");
}
textWriter.Write(b.ToString());
} else {
textWriter.Write(value.ToString());
}
}
static string ConvertCharLiteral(char ch)
{
if (ch == '\'') {
return "\\'";
}
return ConvertChar(ch);
}
/// <summary>
/// Gets the escape sequence for the specified character.
/// </summary>
/// <remarks>This method does not convert ' or ".</remarks>
public static string ConvertChar(char ch)
{
switch (ch) {
case '\\':
return "\\\\";
case '\0':
return "\\0";
case '\a':
return "\\a";
case '\b':
return "\\b";
case '\f':
return "\\f";
case '\n':
return "\\n";
case '\r':
return "\\r";
case '\t':
return "\\t";
case '\v':
return "\\v";
default:
if (char.IsControl(ch) || char.IsSurrogate(ch) ||
// print all uncommon white spaces as numbers
(char.IsWhiteSpace(ch) && ch != ' ')) {
return "\\u" + ((int)ch).ToString("x4");
} else {
return ch.ToString();
}
}
}
/// <summary>
/// Converts special characters to escape sequences within the given string.
/// </summary>
public static string ConvertString(string str)
{
StringBuilder sb = new StringBuilder ();
foreach (char ch in str) {
if (ch == '"') {
sb.Append("\\\"");
} else {
sb.Append(ConvertChar(ch));
}
}
return sb.ToString();
}
public virtual void StartNode(AstNode node)
{
// Write out the indentation, so that overrides of this method

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs

@ -263,13 +263,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -263,13 +263,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return 0;
}
sealed class SegmentTrackingOutputFormatter : TextWriterOutputFormatter
sealed class SegmentTrackingTokenWriter : TextWriterTokenWriter
{
internal List<KeyValuePair<AstNode, Segment>> NewSegments = new List<KeyValuePair<AstNode, Segment>>();
Stack<int> startOffsets = new Stack<int>();
readonly StringWriter stringWriter;
public SegmentTrackingOutputFormatter (StringWriter stringWriter)
public SegmentTrackingTokenWriter(StringWriter stringWriter)
: base(stringWriter)
{
this.stringWriter = stringWriter;
@ -293,7 +293,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -293,7 +293,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
protected NodeOutput OutputNode(int indentLevel, AstNode node, bool startWithNewLine = false)
{
var stringWriter = new StringWriter ();
var formatter = new SegmentTrackingOutputFormatter (stringWriter);
var formatter = new SegmentTrackingTokenWriter(stringWriter);
formatter.Indentation = indentLevel;
formatter.IndentationString = Options.TabsToSpaces ? new string (' ', Options.IndentSize) : "\t";
stringWriter.NewLine = Options.EolMarker;

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpUnresolvedFile.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
/// Represents a file that was parsed and converted for the type system.
/// </summary>
[Serializable, FastSerializerVersion(TypeSystemConvertVisitor.version)]
public sealed class CSharpUnresolvedFile : AbstractFreezable, IUnresolvedFile, IUnresolvedDocumentationProvider
public class CSharpUnresolvedFile : AbstractFreezable, IUnresolvedFile, IUnresolvedDocumentationProvider
{
// The 'FastSerializerVersion' attribute on CSharpUnresolvedFile must be incremented when fixing
// bugs in the TypeSystemConvertVisitor

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CSharpOutputVisitorTests.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp
policy = FormattingOptionsFactory.CreateMono();
StringWriter w = new StringWriter();
w.NewLine = "\n";
node.AcceptVisitor(new CSharpOutputVisitor(new TextWriterOutputFormatter(w) { IndentationString = "$" }, policy));
node.AcceptVisitor(new CSharpOutputVisitor(new TextWriterTokenWriter(w) { IndentationString = "$" }, policy));
Assert.AreEqual(expected.Replace("\r", ""), w.ToString());
}

4
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs

@ -39,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -39,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp
expr.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
StringWriter w = new StringWriter();
w.NewLine = " ";
expr.AcceptVisitor(new CSharpOutputVisitor(new TextWriterOutputFormatter(w) { IndentationString = "" }, policy));
expr.AcceptVisitor(new CSharpOutputVisitor(new TextWriterTokenWriter(w) { IndentationString = "" }, policy));
return w.ToString();
}
@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp
expr.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = false });
StringWriter w = new StringWriter();
w.NewLine = " ";
expr.AcceptVisitor(new CSharpOutputVisitor(new TextWriterOutputFormatter(w) { IndentationString = "" }, policy));
expr.AcceptVisitor(new CSharpOutputVisitor(new TextWriterTokenWriter(w) { IndentationString = "" }, policy));
return w.ToString();
}

Loading…
Cancel
Save