void EndKeywordBlock(IDecompilerOutput output, BraceInfo info, CodeBracesRangeFlags flags, bool addLineSeparator = false) { output.DecreaseIndent(); var end = output.NextPosition; output.Write("}", BoxedTextColor.Punctuation); output.AddBracePair(new TextSpan(info.Start, 1), new TextSpan(end, 1), flags); if (addLineSeparator) { output.AddLineSeparator(end); } output.WriteLine(); }
public override void Decompile(MethodDef method, IDecompilerOutput output, DecompilationContext ctx) { WriteCommentBegin(output, true); output.Write("Method: ", BoxedTextColor.Comment); output.Write(IdentifierEscaper.Escape(method.FullName), method, DecompilerReferenceFlags.Definition, BoxedTextColor.Comment); WriteCommentEnd(output, true); output.WriteLine(); if (!method.HasBody) { return; } var bodyInfo = StartKeywordBlock(output, ".body", method); ILAstBuilder astBuilder = new ILAstBuilder(); ILBlock ilMethod = new ILBlock(CodeBracesRangeFlags.MethodBraces); DecompilerContext context = new DecompilerContext(method.Module, MetadataTextColorProvider) { CurrentType = method.DeclaringType, CurrentMethod = method, CalculateBinSpans = ctx.CalculateBinSpans, }; ilMethod.Body = astBuilder.Build(method, inlineVariables, context); if (abortBeforeStep != null) { new ILAstOptimizer().Optimize(context, ilMethod, abortBeforeStep.Value); } if (context.CurrentMethodIsYieldReturn) { output.Write("yield", BoxedTextColor.Keyword); output.Write(" ", BoxedTextColor.Text); output.WriteLine("return", BoxedTextColor.Keyword); } if (context.CurrentMethodIsAsync) { output.Write("async", BoxedTextColor.Keyword); output.Write("/", BoxedTextColor.Punctuation); output.WriteLine("await", BoxedTextColor.Keyword); } var allVariables = ilMethod.GetSelfAndChildrenRecursive <ILExpression>().Select(e => e.Operand as ILVariable) .Where(v => v != null && !v.IsParameter).Distinct(); foreach (ILVariable v in allVariables) { output.Write(IdentifierEscaper.Escape(v.Name), (object)v.OriginalVariable ?? (object)v.OriginalParameter ?? v.Id, DecompilerReferenceFlags.Local | DecompilerReferenceFlags.Definition, v.IsParameter ? BoxedTextColor.Parameter : BoxedTextColor.Local); if (v.Type != null) { output.Write(" ", BoxedTextColor.Text); output.Write(":", BoxedTextColor.Punctuation); output.Write(" ", BoxedTextColor.Text); if (v.IsPinned) { output.Write("pinned", BoxedTextColor.Keyword); output.Write(" ", BoxedTextColor.Text); } v.Type.WriteTo(output, ILNameSyntax.ShortTypeName); } if (v.GeneratedByDecompiler) { output.Write(" ", BoxedTextColor.Text); var start = output.NextPosition; output.Write("[", BoxedTextColor.Punctuation); output.Write("generated", BoxedTextColor.Keyword); var end = output.NextPosition; output.Write("]", BoxedTextColor.Punctuation); output.AddBracePair(new TextSpan(start, 1), new TextSpan(end, 1), CodeBracesRangeFlags.SquareBrackets); } output.WriteLine(); } var builder = new MethodDebugInfoBuilder(method); foreach (ILNode node in ilMethod.Body) { node.WriteTo(output, builder); if (!node.WritesNewLine) { output.WriteLine(); } } output.AddDebugInfo(builder.Create()); EndKeywordBlock(output, bodyInfo, CodeBracesRangeFlags.MethodBraces, addLineSeparator: true); }
public override void Decompile(MethodDef method, IDecompilerOutput output, DecompilationContext ctx) { WriteCommentBegin(output, true); output.Write("Method: ", BoxedTextColor.Comment); output.Write(IdentifierEscaper.Escape(method.FullName), method, DecompilerReferenceFlags.Definition, BoxedTextColor.Comment); WriteCommentEnd(output, true); output.WriteLine(); if (!method.HasBody) { return; } var bodyInfo = StartKeywordBlock(output, ".body", method); ILAstBuilder astBuilder = new ILAstBuilder(); ILBlock ilMethod = new ILBlock(CodeBracesRangeFlags.MethodBraces); DecompilerContext context = new DecompilerContext(settingsVersion, method.Module, MetadataTextColorProvider) { CurrentType = method.DeclaringType, CurrentMethod = method, CalculateILSpans = ctx.CalculateILSpans, }; ilMethod.Body = astBuilder.Build(method, inlineVariables, context); var stateMachineKind = StateMachineKind.None; MethodDef? inlinedMethod = null; AsyncMethodDebugInfo?asyncInfo = null; string? compilerName = null; if (!(abortBeforeStep is null)) { var optimizer = new ILAstOptimizer(); optimizer.Optimize(context, ilMethod, out stateMachineKind, out inlinedMethod, out asyncInfo, abortBeforeStep.Value); compilerName = optimizer.CompilerName; } if (context.CurrentMethodIsYieldReturn) { output.Write("yield", BoxedTextColor.Keyword); output.Write(" ", BoxedTextColor.Text); output.WriteLine("return", BoxedTextColor.Keyword); } if (context.CurrentMethodIsAsync) { output.Write("async", BoxedTextColor.Keyword); output.Write("/", BoxedTextColor.Punctuation); output.WriteLine("await", BoxedTextColor.Keyword); } var allVariables = ilMethod.GetSelfAndChildrenRecursive <ILExpression>().Select(e => e.Operand as ILVariable) .Where(v => !(v is null) && !v.IsParameter).Distinct(); foreach (ILVariable v in allVariables) { output.Write(IdentifierEscaper.Escape(v.Name), v.GetTextReferenceObject(), DecompilerReferenceFlags.Local | DecompilerReferenceFlags.Definition, v.IsParameter ? BoxedTextColor.Parameter : BoxedTextColor.Local); if (!(v.Type is null)) { output.Write(" ", BoxedTextColor.Text); output.Write(":", BoxedTextColor.Punctuation); output.Write(" ", BoxedTextColor.Text); if (v.IsPinned) { output.Write("pinned", BoxedTextColor.Keyword); output.Write(" ", BoxedTextColor.Text); } v.Type.WriteTo(output, ILNameSyntax.ShortTypeName); } if (v.GeneratedByDecompiler) { output.Write(" ", BoxedTextColor.Text); var start = output.NextPosition; output.Write("[", BoxedTextColor.Punctuation); output.Write("generated", BoxedTextColor.Keyword); var end = output.NextPosition; output.Write("]", BoxedTextColor.Punctuation); output.AddBracePair(new TextSpan(start, 1), new TextSpan(end, 1), CodeBracesRangeFlags.SquareBrackets); } output.WriteLine(); } var localVariables = new HashSet <ILVariable>(GetVariables(ilMethod)); var builder = new MethodDebugInfoBuilder(settingsVersion, stateMachineKind, inlinedMethod ?? method, !(inlinedMethod is null) ? method : null, CreateSourceLocals(localVariables), CreateSourceParameters(localVariables), asyncInfo); builder.CompilerName = compilerName; foreach (ILNode node in ilMethod.Body) { node.WriteTo(output, builder); if (!node.WritesNewLine) { output.WriteLine(); } } output.AddDebugInfo(builder.Create()); EndKeywordBlock(output, bodyInfo, CodeBracesRangeFlags.MethodBraces, addLineSeparator: true); }
public void AddBracePair(int leftStart, int leftEnd, int rightStart, int rightEnd, CodeBracesRangeFlags flags) => output.AddBracePair(TextSpan.FromBounds(leftStart, leftEnd), TextSpan.FromBounds(rightStart, rightEnd), flags);