/* 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; using dnSpy.AsmEditor.Method; using dnSpy.Contracts.Documents; using dnSpy.Contracts.Documents.TreeView; using Emit = dnlib.DotNet.Emit; namespace dnSpy.AsmEditor.Commands { sealed class EditedMethodUpdater { public IEnumerable OriginalNodes { get { yield return ownerNode; } } readonly struct MethodState { readonly Emit.MethodBody body; readonly MethodDefOptions methodDefOptions; readonly bool isBodyModified; public MethodState(MethodDef method, bool isBodyModified) { body = method.MethodBody; methodDefOptions = new MethodDefOptions(method); this.isBodyModified = isBodyModified; } public MethodState(Emit.MethodBody body, MethodDefOptions methodDefOptions, bool isBodyModified) { this.body = body; this.methodDefOptions = methodDefOptions; this.isBodyModified = isBodyModified; } public void CopyTo(MethodDef method, IMethodAnnotations methodAnnotations) { method.MethodBody = body; methodDefOptions.CopyTo(method); methodAnnotations.SetBodyModified(method, isBodyModified); } } readonly Lazy methodAnnotations; readonly MethodNode ownerNode; readonly MethodDef method; readonly MethodState originalMethodState; readonly MethodState newMethodState; public EditedMethodUpdater(Lazy methodAnnotations, ModuleDocumentNode modNode, MethodDef originalMethod, Emit.MethodBody newBody, MethodDefOptions methodDefOptions) { this.methodAnnotations = methodAnnotations; var node = modNode.Context.DocumentTreeView.FindNode(originalMethod); if (node is null) throw new InvalidOperationException(); ownerNode = node; method = originalMethod; originalMethodState = new MethodState(originalMethod, methodAnnotations.Value.IsBodyModified(method)); newMethodState = new MethodState(newBody, methodDefOptions, true); } public void Add() => newMethodState.CopyTo(method, methodAnnotations.Value); public void Remove() => originalMethodState.CopyTo(method, methodAnnotations.Value); } }