/// <summary> /// Reset state of editor and makes copy of actual project content. /// </summary> public void Reset() { changeMade = false; actualEvent = new EditorEvent(); lastProjectContent = new ProjectContentCopy(ParserService.CurrentProjectContent); int count = lastProjectContent.Classes.Count; }
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> /// Loads symbols generated by compiler when comopiling new version of assembly /// to the debugged module ISymUnamagedReader /// </summary> private bool processChanges(EditorEvent edEvent, DeltaBuilder dBuilder) { List<BuildError> errors = SourceChangeValidator.GetErrors(edEvent.changes); if (errors.Count > 0) { showErrors(errors); return false; } else { // register new elements in metadata foreach (SourceChange change in edEvent.changes) { if (change.MemberAction == SourceChangeAction.Created && change.MemberKind == SourceChangeMember.Method) { dBuilder.PreAddMethod((IMethod)change.NewEntity); } } foreach (SourceChange change in edEvent.changes) { dBuilder.MakeChange(change); } return true; } }
/// <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; } }
/// <summary> /// Is called by debugger before continueing in debug. /// </summary> /// <returns>Returns true if succeed.</returns> public bool BeforeContinue() { if (!eventCreator.UpToDate) { lastEvent = eventCreator.GetChanges(); if (!this.patchWithEnC(lastEvent)) { MessageService.ShowError("EnC was not to able to propagate changes. See Errors for detials."); WindowsDebugger winDebugger = DebuggerService.CurrentDebugger as WindowsDebugger; winDebugger.Stop(); return false; } eventCreator.Reset(); } return true; }
public EditorEventCreator(EnC.EnCManager manager) { this.manager = manager; actualEvent = new EditorEvent(); lastProjectContent = new ProjectContentCopy(ParserService.CurrentProjectContent); }