.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

513 lines
20 KiB

//
// DomFormattingVisitor.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
//
// 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 ICSharpCode.NRefactory.CSharp;
using System.Text;
using MonoDevelop.Projects.Dom;
using Mono.TextEditor;
using MonoDevelop.Refactoring;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp
{
public class DomSpacingVisitor : AbtractCSharpDomVisitor<object, object>
{
CSharpFormattingPolicy policy;
TextEditorData data;
List<Change> changes = new List<Change> ();
public List<Change> Changes {
get { return this.changes; }
}
public bool AutoAcceptChanges { get; set; }
public DomSpacingVisitor (CSharpFormattingPolicy policy, TextEditorData data)
{
this.policy = policy;
this.data = data;
AutoAcceptChanges = true;
}
internal class MyTextReplaceChange : TextReplaceChange
{
TextEditorData data;
protected override TextEditorData TextEditorData {
get {
return data;
}
}
public MyTextReplaceChange (TextEditorData data, int offset, int count, string replaceWith)
{
this.data = data;
this.FileName = data.Document.FileName;
this.Offset = offset;
this.RemovedChars = count;
this.InsertedText = replaceWith;
}
}
public override object VisitCompilatioICSharpCode.NRefactory.CSharparp.Dom.CompilationUnit unit, object data)
{
base.VisitCompilationUnit (unit, data);
if (AutoAcceptChanges)
RefactoringService.AcceptChanges (null, null, changes);
return null;
}
public override object VisitTypeDeclaration (TypeDeclaration typeDeclaration, object data)
{
return base.VisitTypeDeclaration (typeDeclaration, data);
}
public override object VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, object data)
{
return base.VisitPropertyDeclaration (propertyDeclaration, data);
}
public override object VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration, object data)
{
ForceSpacesAfter (indexerDeclaration.LBracket, policy.SpacesWithinBrackets);
ForceSpacesBefore (indexerDeclaration.RBracket, policy.SpacesWithinBrackets);
return base.VisitIndexerDeclaration (indexerDeclaration, data);
}
public override object VisitBlockStatement (BlockStatement blockStatement, object data)
{
return base.VisitBlockStatement (blockStatement, data);
}
public override object VisitAssignmentExpression (AssignmentExpression assignmentExpression, object data)
{
ForceSpacesAround (assignmentExpression.Operator, policy.AroundAssignmentParentheses);
return base.VisitAssignmentExpression (assignmentExpression, data);
}
public override object VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression, object data)
{
bool forceSpaces = false;
switch (binaryOperatorExpression.BinaryOperatorType) {
case BinaryOperatorType.Equality:
case BinaryOperatorType.InEquality:
forceSpaces = policy.AroundEqualityOperatorParentheses;
break;
case BinaryOperatorType.GreaterThan:
case BinaryOperatorType.GreaterThanOrEqual:
case BinaryOperatorType.LessThan:
case BinaryOperatorType.LessThanOrEqual:
forceSpaces = policy.AroundRelationalOperatorParentheses;
break;
case BinaryOperatorType.LogicalAnd:
case BinaryOperatorType.LogicalOr:
forceSpaces = policy.AroundLogicalOperatorParentheses;
break;
case BinaryOperatorType.BitwiseAnd:
case BinaryOperatorType.BitwiseOr:
case BinaryOperatorType.ExclusiveOr:
forceSpaces = policy.AroundBitwiseOperatorParentheses;
break;
case BinaryOperatorType.Add:
case BinaryOperatorType.Subtract:
forceSpaces = policy.AroundAdditiveOperatorParentheses;
break;
case BinaryOperatorType.Multiply:
case BinaryOperatorType.Divide:
case BinaryOperatorType.Modulus:
forceSpaces = policy.AroundMultiplicativeOperatorParentheses;
break;
case BinaryOperatorType.ShiftLeft:
case BinaryOperatorType.ShiftRight:
forceSpaces = policy.AroundShiftOperatorParentheses;
break;
}
ForceSpacesAround (binaryOperatorExpression.Operator, forceSpaces);
return base.VisitBinaryOperatorExpression (binaryOperatorExpression, data);
}
public override object VisitConditionalExpression (ConditionalExpression conditionalExpression, object data)
{
ForceSpacesBefore (conditionalExpression.QuestionMark, policy.ConditionalOperatorBeforeConditionSpace);
ForceSpacesAfter (conditionalExpression.QuestionMark, policy.ConditionalOperatorAfterConditionSpace);
ForceSpacesBefore (conditionalExpression.Colon, policy.ConditionalOperatorBeforeSeparatorSpace);
ForceSpacesAfter (conditionalExpression.Colon, policy.ConditionalOperatorAfterSeparatorSpace);
return base.VisitConditionalExpression (conditionalExpression, data);
}
public override object VisitCastExpression (CastExpression castExpression, object data)
{
if (castExpression.RPar != null) {
ForceSpacesAfter (castExpression.LPar, policy.WithinCastParentheses);
ForceSpacesBefore (castExpression.RPar, policy.WithinCastParentheses);
ForceSpacesAfter (castExpression.RPar, 1, policy.SpacesAfterTypecast);
}
return base.VisitCastExpression (castExpression, data);
}
void ForceSpacesAround (INode node, bool forceSpaces)
{
ForceSpacesBefore (node, forceSpaces);
ForceSpacesAfter (node, forceSpaces);
}
void ForceSpacesAfter (INode node, bool forceSpaces)
{
DomLocation location = ((ICSharpNode)node).EndLocation;
int offset = data.Document.LocationToOffset (location.Line, location.Column) - 1;
int i = offset + 1;
while (i < data.Document.Length && Char.IsWhiteSpace (data.Document.GetCharAt (i))) {
i++;
}
ForceSpace (offset, i, forceSpaces);
}
void ForceSpacesAfter (INode node, int tokenLength, bool forceSpaces)
{
DomLocation location = ((ICSharpNode)node).StartLocation;
int offset = data.Document.LocationToOffset (location.Line, location.Column) + 1;
int i = offset;
while (i < data.Document.Length && Char.IsWhiteSpace (data.Document.GetCharAt (i))) {
i++;
}
ForceSpace (offset - 1, i, forceSpaces);
}
int ForceSpacesBefore (INode node, bool forceSpaces)
{
DomLocation location = ((ICSharpNode)node).StartLocation;
int offset = data.Document.LocationToOffset (location.Line, location.Column);
int i = offset - 1;
while (i >= 0 && Char.IsWhiteSpace (data.Document.GetCharAt (i))) {
i--;
}
ForceSpace (i, offset, forceSpaces);
return i;
}
public override object VisitFieldDeclaration (FieldDeclaration fieldDeclaration, object data)
{
foreach (INode node in fieldDeclaration.Children) {
if (node is VariableInitializer && node.NextSibling != null && node.NextSibling.Role == FieldDeclaration.Roles.Comma) {
VariableInitializer initializer = node as VariableInitializer;
CSharpTokenNode commaToken = (CSharpTokenNode)node.NextSibling;
int offset = this.data.Document.LocationToOffset (initializer.NameIdentifier.StartLocation.Line, initializer.NameIdentifier.StartLocation.Column);
int commaOffset = this.data.Document.LocationToOffset (commaToken.StartLocation.Line, commaToken.StartLocation.Column);
ForceSpace (offset, commaOffset, policy.SpacesAfterComma);
//Console.WriteLine (initializer.Name +"/" + initializer.NameIdentifier + "/" + commaToken);
if (node.NextSibling.NextSibling is VariableInitializer) {
DomLocation location = ((VariableInitializer)node.NextSibling.NextSibling).NameIdentifier.StartLocation;
int nextOffset = this.data.Document.LocationToOffset (location.Line, location.Column);
ForceSpace (commaOffset, nextOffset, policy.SpacesAfterComma);
}
}
}
return base.VisitFieldDeclaration (fieldDeclaration, data);
}
public override object VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration, object data)
{
CSharpTokenNode lParen = (CSharpTokenNode)delegateDeclaration.GetChildByRole (DelegateDeclaration.Roles.LPar);
int offset = this.data.Document.LocationToOffset (lParen.StartLocation.Line, lParen.StartLocation.Column);
ForceSpaceBefore (offset, policy.BeforeDelegateDeclarationParentheses);
return base.VisitDelegateDeclaration (delegateDeclaration, data);
}
public override object VisitMethodDeclaration (MethodDeclaration methodDeclaration, object data)
{
ForceSpacesBefore (methodDeclaration.LPar, policy.BeforeMethodDeclarationParentheses);
ForceSpacesAfter (methodDeclaration.LPar, policy.WithinMethodDeclarationParentheses);
ForceSpacesBefore (methodDeclaration.RPar, policy.WithinMethodDeclarationParentheses);
return base.VisitMethodDeclaration (methodDeclaration, data);
}
public override object VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, object data)
{
CSharpTokenNode lParen = (CSharpTokenNode)constructorDeclaration.GetChildByRole (ConstructorDeclaration.Roles.LPar);
int offset = this.data.Document.LocationToOffset (lParen.StartLocation.Line, lParen.StartLocation.Column);
ForceSpaceBefore (offset, policy.BeforeConstructorDeclarationParentheses);
return base.VisitConstructorDeclaration (constructorDeclaration, data);
}
public override object VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, object data)
{
CSharpTokenNode lParen = (CSharpTokenNode)destructorDeclaration.GetChildByRole (DestructorDeclaration.Roles.LPar);
int offset = this.data.Document.LocationToOffset (lParen.StartLocation.Line, lParen.StartLocation.Column);
ForceSpaceBefore (offset, policy.BeforeConstructorDeclarationParentheses);
return base.VisitDestructorDeclaration (destructorDeclaration, data);
}
void ForceSpaceBefore (int offset, bool forceSpace)
{
bool insertedSpace = false;
do {
char ch = data.Document.GetCharAt (offset);
//Console.WriteLine (ch);
if (!Char.IsWhiteSpace (ch) && (insertedSpace || !forceSpace))
break;
if (ch == ' ' && forceSpace) {
if (insertedSpace) {
changes.Add (new MyTextReplaceChange (data, offset, 1, null));
} else {
insertedSpace = true;
}
} else if (forceSpace) {
if (!insertedSpace) {
changes.Add (new MyTextReplaceChange (data, offset, Char.IsWhiteSpace (ch) ? 1 : 0, " "));
insertedSpace = true;
} else if (Char.IsWhiteSpace (ch)) {
changes.Add (new MyTextReplaceChange (data, offset, 1, null));
}
}
offset--;
} while (offset >= 0);
}
void ForceSpace (int startOffset, int endOffset, bool forceSpace)
{
int lastNonWs = SearchLastNonWsChar (startOffset, endOffset);
changes.Add (new MyTextReplaceChange (data, lastNonWs + 1, System.Math.Max (0, endOffset - lastNonWs - 1), forceSpace ? " " : ""));
}
int SearchLastNonWsChar (int startOffset, int endOffset)
{
startOffset = System.Math.Max (0, startOffset);
endOffset = System.Math.Max (startOffset, endOffset);
if (startOffset >= endOffset)
return startOffset;
int result = -1;
bool inComment = false;
for (int i = startOffset; i < endOffset && i < data.Document.Length; i++) {
char ch = data.Document.GetCharAt (i);
//Console.WriteLine (ch);
if (Char.IsWhiteSpace (ch))
continue;
if (ch == '/' && i + 1 < data.Document.Length && data.Document.GetCharAt (i + 1) == '/')
return result;
if (ch == '/' && i + 1 < data.Document.Length && data.Document.GetCharAt (i + 1) == '*') {
inComment = true;
i++;
continue;
}
if (inComment && ch == '*' && i + 1 < data.Document.Length && data.Document.GetCharAt (i + 1) == '/') {
inComment = false;
i++;
continue;
}
if (!inComment)
result = i;
}
return result;
}
public override object VisitInvocationExpression (InvocationExpression invocationExpression, object data)
{
ForceSpacesBefore (invocationExpression.LPar, policy.BeforeMethodCallParentheses);
ForceSpacesAfter (invocationExpression.LPar, policy.WithinMethodCallParentheses);
ForceSpacesBefore (invocationExpression.RPar, policy.WithinMethodCallParentheses);
return base.VisitInvocationExpression (invocationExpression, data);
}
public override object VisitIndexerExpression (IndexerExpression indexerExpression, object data)
{
ForceSpacesAfter (indexerExpression.LBracket, policy.SpacesWithinBrackets);
ForceSpacesBefore (indexerExpression.RBracket, policy.SpacesWithinBrackets);
return base.VisitIndexerExpression (indexerExpression, data);
}
public override object VisitIfElseStatement (IfElseStatement ifElseStatement, object data)
{
ForceSpacesBefore (ifElseStatement.LPar, policy.IfParentheses);
ForceSpacesAfter (ifElseStatement.LPar, policy.WithinIfParentheses);
ForceSpacesBefore (ifElseStatement.RPar, policy.WithinIfParentheses);
return base.VisitIfElseStatement (ifElseStatement, data);
}
public override object VisitWhileStatement (WhileStatement whileStatement, object data)
{
ForceSpacesBefore (whileStatement.LPar, policy.WhileParentheses);
ForceSpacesAfter (whileStatement.LPar, policy.WithinWhileParentheses);
ForceSpacesBefore (whileStatement.RPar, policy.WithinWhileParentheses);
return base.VisitWhileStatement (whileStatement, data);
}
public override object VisitForStatement (ForStatement forStatement, object data)
{
foreach (INode node in forStatement.Children) {
if (node.Role == ForStatement.Roles.Semicolon) {
if (node.NextSibling is CSharpTokenNode || node.NextSibling is EmptyStatement)
continue;
ForceSpacesAfter (node, policy.SpacesAfterSemicolon);
}
}
ForceSpacesBefore (forStatement.LPar, policy.ForParentheses);
ForceSpacesAfter (forStatement.LPar, policy.WithinForParentheses);
ForceSpacesBefore (forStatement.RPar, policy.WithinForParentheses);
if (forStatement.EmbeddedStatement != null)
forStatement.EmbeddedStatement.AcceptVisitor (this, data);
return null;
}
public override object VisitForeachStatement (ForeachStatement foreachStatement, object data)
{
ForceSpacesBefore (foreachStatement.LPar, policy.ForeachParentheses);
ForceSpacesAfter (foreachStatement.LPar, policy.WithinForEachParentheses);
ForceSpacesBefore (foreachStatement.RPar, policy.WithinForEachParentheses);
return base.VisitForeachStatement (foreachStatement, data);
}
public override object VisitCatchClause (CatchClause catchClause, object data)
{
if (catchClause.LPar != null) {
ForceSpacesBefore (catchClause.LPar, policy.CatchParentheses);
ForceSpacesAfter (catchClause.LPar, policy.WithinCatchParentheses);
ForceSpacesBefore (catchClause.RPar, policy.WithinCatchParentheses);
}
return base.VisitCatchClause (catchClause, data);
}
public override object VisitLockStatement (LockStatement lockStatement, object data)
{
ForceSpacesBefore (lockStatement.LPar, policy.LockParentheses);
ForceSpacesAfter (lockStatement.LPar, policy.WithinLockParentheses);
ForceSpacesBefore (lockStatement.RPar, policy.WithinLockParentheses);
return base.VisitLockStatement (lockStatement, data);
}
public override object VisitUsingStatement (UsingStatement usingStatement, object data)
{
ForceSpacesBefore (usingStatement.LPar, policy.UsingParentheses);
ForceSpacesAfter (usingStatement.LPar, policy.WithinUsingParentheses);
ForceSpacesBefore (usingStatement.RPar, policy.WithinUsingParentheses);
return base.VisitUsingStatement (usingStatement, data);
}
public override object VisitSwiICSharpCode.NRefactory.CSharplop.CSharp.Dom.SwitchStatement switchStatement, object data)
{
ForceSpacesBefore (switchStatement.LPar, policy.SwitchParentheses);
ForceSpacesAfter (switchStatement.LPar, policy.WithinSwitchParentheses);
ForceSpacesBefore (switchStatement.RPar, policy.WithinSwitchParentheses);
return base.VisitSwitchStatement (switchStatement, data);
}
public override object VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression, object data)
{
ForceSpacesAfter (parenthesizedExpression.LPar, policy.WithinParentheses);
ForceSpacesBefore (parenthesizedExpression.RPar, policy.WithinParentheses);
return base.VisitParenthesizedExpression (parenthesizedExpression, data);
}
public override object VisitSizeOfExpression (SizeOfExpression sizeOfExpression, object data)
{
ForceSpacesAfter (sizeOfExpression.LPar, policy.WithinSizeOfParentheses);
ForceSpacesBefore (sizeOfExpression.RPar, policy.WithinSizeOfParentheses);
return base.VisitSizeOfExpression (sizeOfExpression, data);
}
public override object VisitTypeOfExpression (TypeOfExpression typeOfExpression, object data)
{
ForceSpacesAfter (typeOfExpression.LPar, policy.WithinTypeOfParentheses);
ForceSpacesBefore (typeOfExpression.RPar, policy.WithinTypeOfParentheses);
return base.VisitTypeOfExpression (typeOfExpression, data);
}
public override object VisitCheckedExpression (CheckedExpression checkedExpression, object data)
{
ForceSpacesAfter (checkedExpression.LPar, policy.WithinCheckedExpressionParantheses);
ForceSpacesBefore (checkedExpression.RPar, policy.WithinCheckedExpressionParantheses);
return base.VisitCheckedExpression (checkedExpression, data);
}
public override object VisitUncheckedExpression (UncheckedExpression uncheckedExpression, object data)
{
ForceSpacesAfter (uncheckedExpression.LPar, policy.WithinCheckedExpressionParantheses);
ForceSpacesBefore (uncheckedExpression.RPar, policy.WithinCheckedExpressionParantheses);
return base.VisitUncheckedExpression (uncheckedExpression, data);
}
public override object VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression, object data)
{
ForceSpacesBefore (objectCreateExpression.LPar, policy.NewParentheses);
return base.VisitObjectCreateExpression (objectCreateExpression, data);
}
public override object VisitArrayObjectCreateExpression (ArrayObjectCreateExpression arrayObjectCreateExpression, object data)
{
foreach (INode node in arrayObjectCreateExpression.Children) {
if (node.Role == ArrayObjectCreateExpression.Roles.Comma) {
ForceSpacesBefore (node, policy.SpacesBeforeComma);
ForceSpacesAfter (node, policy.SpacesAfterComma);
}
}
return base.VisitArrayObjectCreateExpression (arrayObjectCreateExpression, data);
}
public override object VisitLambdaExpression (LambdaExpression lambdaExpression, object data)
{
ForceSpacesAfter (lambdaExpression.Arrow, true);
ForceSpacesBefore (lambdaExpression.Arrow, true);
return base.VisitLambdaExpression (lambdaExpression, data);
}
}
}
*/