/// <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> /// Creates <see cref="SequencePointRemapper">SequencePointRemapper</see> - sequence point difference tool for /// specified method used in debug state refreshing and local variables definition. /// </summary> /// <param name="methodDef">Method to which generating takes place.</param> /// <returns>Instance of <see cref="SequencePointRemapper">SequencePointRemapper</see>.</returns> private SequencePointRemapper genSequencePointRemapper(MethodDefinition methodDefOld, MethodDefinition methodDefNew) { uint token = methodDefOld.MetadataToken.ToUInt32(); List <SequencePoint> oldSeqs = SymbolWriterClass.GetMethodSequencePoints( Manager.ResourceManager.CurrentModule.SymReader, methodDefOld.MetadataToken.ToUInt32()); List <SequencePoint> newSeqs = SymbolWriterClass.GetMethodSequencePoints( SymbolWriter.CorSymNewReader, methodDefNew.MetadataToken.ToUInt32()); SequencePointRemapper remapper = new SequencePointRemapper(oldSeqs, newSeqs, Manager.ActualEditEvent.sourceTextChanges[token]); SequencePointRemappers.Add(token, remapper); return(remapper); }
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); } } } } }
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()); }
/// <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) { } }
/// <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); } }