mirror of https://github.com/icsharpcode/ILSpy.git
				
				
			
			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.
		
		
		
		
		
			
		
			
				
					
					
						
							144 lines
						
					
					
						
							4.3 KiB
						
					
					
				
			
		
		
	
	
							144 lines
						
					
					
						
							4.3 KiB
						
					
					
				using System; | 
						|
using System.Collections.Generic; | 
						|
using System.Linq; | 
						|
using System.Text; | 
						|
using ICSharpCode.Decompiler.CSharp.Syntax; | 
						|
using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; | 
						|
 | 
						|
namespace ICSharpCode.Decompiler.CSharp.Transforms | 
						|
{ | 
						|
	class NormalizeBlockStatements : DepthFirstAstVisitor, IAstTransform | 
						|
	{ | 
						|
		TransformContext context; | 
						|
 | 
						|
		public override void VisitIfElseStatement(IfElseStatement ifElseStatement) | 
						|
		{ | 
						|
			base.VisitIfElseStatement(ifElseStatement); | 
						|
			DoTransform(ifElseStatement.TrueStatement, ifElseStatement); | 
						|
			DoTransform(ifElseStatement.FalseStatement, ifElseStatement); | 
						|
		} | 
						|
 | 
						|
		public override void VisitWhileStatement(WhileStatement whileStatement) | 
						|
		{ | 
						|
			base.VisitWhileStatement(whileStatement); | 
						|
			InsertBlock(whileStatement.EmbeddedStatement); | 
						|
		} | 
						|
 | 
						|
		public override void VisitDoWhileStatement(DoWhileStatement doWhileStatement) | 
						|
		{ | 
						|
			base.VisitDoWhileStatement(doWhileStatement); | 
						|
			InsertBlock(doWhileStatement.EmbeddedStatement); | 
						|
		} | 
						|
 | 
						|
		public override void VisitForeachStatement(ForeachStatement foreachStatement) | 
						|
		{ | 
						|
			base.VisitForeachStatement(foreachStatement); | 
						|
			InsertBlock(foreachStatement.EmbeddedStatement); | 
						|
		} | 
						|
 | 
						|
		public override void VisitForStatement(ForStatement forStatement) | 
						|
		{ | 
						|
			base.VisitForStatement(forStatement); | 
						|
			InsertBlock(forStatement.EmbeddedStatement); | 
						|
		} | 
						|
 | 
						|
		public override void VisitFixedStatement(FixedStatement fixedStatement) | 
						|
		{ | 
						|
			base.VisitFixedStatement(fixedStatement); | 
						|
			InsertBlock(fixedStatement.EmbeddedStatement); | 
						|
		} | 
						|
 | 
						|
		public override void VisitLockStatement(LockStatement lockStatement) | 
						|
		{ | 
						|
			base.VisitLockStatement(lockStatement); | 
						|
			InsertBlock(lockStatement.EmbeddedStatement); | 
						|
		} | 
						|
 | 
						|
		public override void VisitUsingStatement(UsingStatement usingStatement) | 
						|
		{ | 
						|
			base.VisitUsingStatement(usingStatement); | 
						|
			DoTransform(usingStatement.EmbeddedStatement, usingStatement); | 
						|
		} | 
						|
 | 
						|
		void DoTransform(Statement statement, Statement parent) | 
						|
		{ | 
						|
			if (statement.IsNull) return; | 
						|
			if (context.Settings.AlwaysUseBraces) { | 
						|
				if (!IsElseIf(statement, parent)) { | 
						|
					InsertBlock(statement); | 
						|
				} | 
						|
			} else { | 
						|
				if (statement is BlockStatement b && b.Statements.Count == 1 && IsAllowedAsEmbeddedStatement(b.Statements.First(), parent)) { | 
						|
					statement.ReplaceWith(b.Statements.First().Detach()); | 
						|
				} else if (!IsAllowedAsEmbeddedStatement(statement, parent)) { | 
						|
					InsertBlock(statement); | 
						|
				} | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		bool IsElseIf(Statement statement, Statement parent) | 
						|
		{ | 
						|
			return parent is IfElseStatement && statement.Role == IfElseStatement.FalseRole; | 
						|
		} | 
						|
 | 
						|
		static void InsertBlock(Statement statement) | 
						|
		{ | 
						|
			if (statement.IsNull) return; | 
						|
			if (!(statement is BlockStatement)) { | 
						|
				var b = new BlockStatement(); | 
						|
				statement.ReplaceWith(b); | 
						|
				b.Add(statement); | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		bool IsAllowedAsEmbeddedStatement(Statement statement, Statement parent) | 
						|
		{ | 
						|
			switch (statement) { | 
						|
				case IfElseStatement ies: | 
						|
					return parent is IfElseStatement && ies.Role == IfElseStatement.FalseRole; | 
						|
				case VariableDeclarationStatement vds: | 
						|
				case WhileStatement ws: | 
						|
				case DoWhileStatement dws: | 
						|
				case SwitchStatement ss: | 
						|
				case ForeachStatement fes: | 
						|
				case ForStatement fs: | 
						|
				case LockStatement ls: | 
						|
				case FixedStatement fxs: | 
						|
					return false; | 
						|
				case UsingStatement us: | 
						|
					return parent is UsingStatement; | 
						|
				default: | 
						|
					return !(parent?.Parent is IfElseStatement); | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		void IAstTransform.Run(AstNode rootNode, TransformContext context) | 
						|
		{ | 
						|
			this.context = context; | 
						|
			rootNode.AcceptVisitor(this); | 
						|
		} | 
						|
 | 
						|
		public override void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration) | 
						|
		{ | 
						|
			if (context.Settings.UseExpressionBodyForCalculatedGetterOnlyProperties) { | 
						|
				SimplifyPropertyDeclaration(propertyDeclaration); | 
						|
			} | 
						|
			base.VisitPropertyDeclaration(propertyDeclaration); | 
						|
		} | 
						|
 | 
						|
		static readonly PropertyDeclaration CalculatedGetterOnlyPropertyPattern = new PropertyDeclaration() { | 
						|
			Modifiers = Modifiers.Any, | 
						|
			Name = Pattern.AnyString, | 
						|
			ReturnType = new AnyNode(), | 
						|
			Getter = new Accessor() { Body = new BlockStatement() { new ReturnStatement(new AnyNode("expression")) } } | 
						|
		}; | 
						|
 | 
						|
		void SimplifyPropertyDeclaration(PropertyDeclaration propertyDeclaration) | 
						|
		{ | 
						|
			var m = CalculatedGetterOnlyPropertyPattern.Match(propertyDeclaration); | 
						|
			if (!m.Success) | 
						|
				return; | 
						|
			propertyDeclaration.ExpressionBody = m.Get<Expression>("expression").Single().Detach(); | 
						|
		} | 
						|
	} | 
						|
}
 | 
						|
 |