/*
Copyright (C) 2014-2019 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see .
*/
using System;
using System.Collections.Generic;
using dnlib.DotNet;
namespace dnSpy.Contracts.Decompiler {
///
/// Builds instances
///
public sealed class MethodDebugInfoBuilder {
readonly MethodDef method;
readonly MethodDef? kickoffMethod;
readonly StateMachineKind stateMachineKind;
readonly List statements;
///
/// Compiler name () or null
///
public string? CompilerName { get; set; }
///
/// Gets the scope builder
///
public MethodDebugScopeBuilder Scope { get; }
///
/// Gets/sets the parameters
///
public SourceParameter[]? Parameters { get; set; }
///
/// Async method debug info or null
///
public AsyncMethodDebugInfo? AsyncInfo { get; set; }
///
/// Start of method (eg. position of the first character of the modifier or return type)
///
public int? StartPosition { get; set; }
///
/// End of method (eg. after the last brace)
///
public int? EndPosition { get; set; }
readonly int decompilerSettingsVersion;
///
/// Constructor
///
/// Decompiler settings version number. This version number should get incremented when the settings change.
/// State machine kind
/// Method
/// Kickoff method or null
public MethodDebugInfoBuilder(int decompilerSettingsVersion, StateMachineKind stateMachineKind, MethodDef method, MethodDef? kickoffMethod) {
this.decompilerSettingsVersion = decompilerSettingsVersion;
this.stateMachineKind = stateMachineKind;
this.method = method ?? throw new ArgumentNullException(nameof(method));
this.kickoffMethod = kickoffMethod;
statements = new List();
Scope = new MethodDebugScopeBuilder();
Scope.Span = ILSpan.FromBounds(0, (uint)method.Body.GetCodeSize());
if (method == kickoffMethod)
throw new ArgumentException();
}
///
/// Constructor
///
/// Decompiler settings version number. This version number should get incremented when the settings change.
/// State machine kind
/// Method
/// Kickoff method or null
/// Locals
/// Parameters or null
/// Async method info or null
public MethodDebugInfoBuilder(int decompilerSettingsVersion, StateMachineKind stateMachineKind, MethodDef method, MethodDef? kickoffMethod, SourceLocal[] locals, SourceParameter[]? parameters, AsyncMethodDebugInfo? asyncInfo)
: this(decompilerSettingsVersion, stateMachineKind, method, kickoffMethod) {
Scope.Locals.AddRange(locals);
Parameters = parameters;
AsyncInfo = asyncInfo;
}
///
/// Adds a
///
/// Statement
public void Add(SourceStatement statement) => statements.Add(statement);
///
/// Creates a
///
///
public MethodDebugInfo Create() {
TextSpan? methodSpan;
if (StartPosition is not null && EndPosition is not null && StartPosition.Value <= EndPosition.Value)
methodSpan = TextSpan.FromBounds(StartPosition.Value, EndPosition.Value);
else
methodSpan = null;
return new MethodDebugInfo(CompilerName, decompilerSettingsVersion, stateMachineKind, method, kickoffMethod, Parameters, statements.ToArray(), Scope.ToScope(), methodSpan, AsyncInfo);
}
}
}