/// <summary> /// Updates symbol store. /// </summary> /// <param name="writer">Class containing emitted symbols.</param> private void updateSymbolStore(SymbolWriterClass writer) { string name = writer.DeltaPDBPath + ".pdb"; try { resource.CurrentModule.SymReader.__UpdateSymbolStore(name, writer.GetSymbolsStream()); } catch (COMException e) { switch ((ulong)e.ErrorCode) { case 0x806D0002: throw new TranslatingException("PDB - in use."); case 0x806D0003: throw new TranslatingException("PDB - Out of memory exception."); case 0x806D0004: throw new TranslatingException("PDB - File system error."); case 0x806D0005: throw new TranslatingException("PDB - not found."); } } }
private void regenMovedSymbolsProperty(IProperty property, SymbolWriterClass emitter) { PropertyDefinition targtProp, targtPropOld; MethodDefinition targtMetSet, targtMetOldSet, targtMetGet, targtMetOldGet; // Find appropriete new version of method in new assembly. targtProp = MetadataManager.FindProperty(ResourceManager.NewAssembly, ResourceManager.NewAssemblyName, property); if (targtProp == null) throw new TranslatingException("Property " + property.ToString() + " could not be found in debugged module"); // Find appropriete original version of method in running assembly. targtPropOld = MetadataManager.FindProperty(ResourceManager.OldAssembly, ResourceManager.CurrentModule.Name, property); if (targtPropOld == null) throw new TranslatingException("Property "+property.ToString()+" could not be found in emitted module"); targtMetGet = targtProp.GetMethod; targtMetSet = targtProp.SetMethod; targtMetOldGet = targtPropOld.GetMethod; targtMetOldSet = targtPropOld.SetMethod; try { if (targtMetGet != null) emitter.EmitMethod(targtMetOldGet.MetadataToken.ToUInt32(), targtMetGet.MetadataToken.ToUInt32()); if (targtMetSet != null) emitter.EmitMethod(targtMetOldSet.MetadataToken.ToUInt32(), targtMetSet.MetadataToken.ToUInt32()); } catch (COMException e) { } }
private void regenMovedSymbolsMethod(IMethod method, SymbolWriterClass emitter) { MethodDefinition targtMet, targtMetOld; // Find appropriete new version of method in new assembly. targtMet = MetadataManager.FindMethod(ResourceManager.NewAssembly, ResourceManager.NewAssemblyName, method); if (targtMet == null) throw new TranslatingException("Method "+method.ToString()+" could not be found in debugged module"); // Find appropriete original version of method in running assembly. targtMetOld = MetadataManager.FindMethod(ResourceManager.OldAssembly, ResourceManager.CurrentModule.Name, method); if (targtMetOld == null) throw new TranslatingException("Method " + method.ToString() + " could not be found in emitted module"); emitter.EmitMethod(targtMetOld.MetadataToken.ToUInt32(), targtMet.MetadataToken.ToUInt32()); }
private void regenMovedSymbolsClass(IClass cClass, EditorEvent edEvent, SymbolWriterClass emitter) { Predicate<string> del = delegate(string name){ return FileUtility.IsEqualFileName(name, cClass.CompilationUnit.FileName); }; if (edEvent.touched.Exists(del)) { if (cClass is CompoundClass) { foreach(IClass tClass in ((CompoundClass)cClass).Parts){ regenMovedSymbolsClass(tClass, edEvent, emitter); } } else { foreach(IMethod method in cClass.Methods) { if(!edEvent.changes.Exists(delegate(SourceChange change){ return change.NewEntity is IMethod && MemberComparator.SameMethodOverloads(method, (IMethod)change.NewEntity); })){ regenMovedSymbolsMethod(method, emitter); } } foreach (IClass tClass in cClass.InnerClasses) { regenMovedSymbolsClass(tClass, edEvent, emitter); } foreach (IProperty tProp in cClass.Properties) { if(!edEvent.changes.Exists(delegate(SourceChange change){ return change.NewEntity is IProperty && MemberComparator.SameProperties(tProp, (IProperty)change.NewEntity); })){ regenMovedSymbolsProperty(tProp, emitter); } } } } }
/// <summary> /// Regenerate source symbols for methods moved by editting others. /// </summary> /// <param name="emitter">Symbol emitting interface.</param> /// <param name="edEvent">EditorEvent containing changed files.</param> private void regenMovedSymbols(SymbolWriterClass emitter, EditorEvent edEvent) { foreach (IClass cClass in ParserService.CurrentProjectContent.Classes) { regenMovedSymbolsClass(cClass,edEvent,emitter); } }
/// <summary> /// This methods is called after trying to continue with editted code. /// It gets a result of searching changes in code and applies them to /// running process if it is possible. /// <param name="eventLog">Contains changes done to code during pause.</param> /// </summary> private bool patchWithEnC(EditorEvent eventLog) { // Build new version of assembly. resource.Load(eventLog.touched); // Exit when errors in compiling if (!resource.CompileSuccessful) { return false; } metadata.Update(); byte[] dmeta = null, dil = null; DeltaBuilder dBuilder = new DeltaBuilder(this); // Initialize symbol emitter. SymbolWriterClass dWriter = new SymbolWriterClass(this, metadata); dWriter.Initialize(metadata.OldEmitter.CorMetaDataEmit, metadata.NewImporter.CorMetaDataImport); dBuilder.SymbolWriter = dWriter; // Process changes and tries to make delta metadata and IL code. // If changes not valid exits. try { if (!processChanges(eventLog, dBuilder)) { return false; } process.AppDomains.ForEach(delegate(AppDomain app) { app.ResetCache(); }); regenMovedSymbols(dWriter, lastEvent); // Update symbols emitted during changes. updateSymbolStore(dWriter); dWriter.Close(); // Recieve deltas and applies them to running module dil = dBuilder.getDeltaIL(); dmeta = dBuilder.getDeltaMetadata(); resource.CurrentModule.ApplyChanges(dmeta, dil); // Log output if in debug mode if (debugMode) { StreamWriter writer = new StreamWriter(resource.TemporaryPath + "enc_log_il"); writer.BaseStream.Write(dil, 0, dil.Length); writer.Flush(); writer.Close(); writer = new StreamWriter(resource.TemporaryPath + "enc_log_meta"); writer.BaseStream.Write(dmeta, 0, dmeta.Length); writer.Flush(); writer.Close(); } funcRemap = new FunctionRemapper(this, dBuilder.SequencePointRemappers); updateBreakpoints(); return true; } catch (TranslatingException e) { dWriter.Close(); TaskService.Clear(); WorkbenchSingleton.SafeThreadAsyncCall( delegate() { TaskService.Clear(); TaskService.Add(new Task(null, e.Message, 0, 0, TaskType.Error)); } ); return false; } }