/diffs/LizardDiff/Diff3Docs/Output.cs
C# | 611 lines | 533 code | 57 blank | 21 comment | 123 complexity | 957aa00ee095d4c3ec0d2d65831bffa9 MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Text;
-
- namespace Ltf.Diffs.Diff3Docs
- {
- //nb. synced with / subset of line state
- public enum ChangeRegionState
- {
- None = 0,
- Conflict = 10,
- Merged = 104,
- UnMerged = 105,
- Resolved = 106,
- UserEdited = 150
- }
-
- public enum ChangeRegionLocation
- {
- Here,
- Above,
- Below
- }
-
- public class ChangeRegion
- {
- public ChangeRegionState State;
- public ChangeRegionLocation Location;
- public int Start, End;
- public List<string> TheirLines = null;
- public List<string> YourLines = null;
- public List<string> Resolution = null;
- public List<string> MergedText = null;
- public List<string> PreviousText = null; // does not appear to be used
- public List<string> EditText = null;
-
- public ChangeRegion(int start, int end, List<string> theirs, List<string> yours)
- {
- this.Start = start;
- this.End = end;
- TheirLines = theirs;
- YourLines = yours;
- State = ChangeRegionState.Conflict;
- Location = ChangeRegionLocation.Here;
- }
- public ChangeRegion(int start, int end, List<string> mergedText, List<string> previousText, ChangeRegionState state, ChangeRegionLocation location)
- {
- this.Start = start;
- this.End = end;
- MergedText = mergedText;
- PreviousText = previousText;
- State = state;
- Location = location;
- }
- }
-
- public class Output : DiffDocument
- {
- const string OutputTextRangeDeleted = "<< Range Deleted >>";
- const string OutputTextNoContext = "<< No matching context >>";
-
- public Output(string fileName)
- : base(fileName) { }
-
- public override void LoadResults(Diff3Results results)
- {
- // showing base and server changes - added lines to keep in sync with local
- // main file based on server file.
- int blankLineOffset = 0;
-
- foreach (Diff3Results.Diff3Hunk hunk in results.Hunks)
- {
- bool insertOffSetAdj = hunk.LocalRange.IsAdd ? false : true;
- LineState insertLineState = hunk.IsAllDiff ? LineState.MergeTheirs : LineState.MergedOkay;
- LineState markLineState = LineState.MergeYours;
- int extraOffset = 0;
-
- List<string> removedLines = new List<string>();
-
- if (hunk.IsAllDiff && hunk.ServerRange.IsAdd)
- AddSpecialLine(hunk.LocalRange.From, ref blankLineOffset, LineState.MergeNoLinesTheirs, OutputTextRangeDeleted, true);
-
- if (hunk.IsAllDiff || hunk.IsServerDiff)
- {
- if (hunk.IsServerDiff && !hunk.LocalRange.IsAdd)
- {
- removedLines = RemoveLines(hunk, ref blankLineOffset);
- extraOffset = hunk.LocalRange.Interval;
- }
-
- if (!hunk.ServerRange.IsAdd)
- InsertChanges(hunk.LocalRange.From, insertLineState, hunk.ServerLines, ref blankLineOffset, insertOffSetAdj, extraOffset, removedLines);
- }
-
- if (hunk.IsAllDiff)
- {
- if (!hunk.LocalRange.IsAdd)
- MarkChanges(hunk.LocalRange.From, markLineState, hunk.LocalRange.Interval, blankLineOffset, true);
-
- if (hunk.LocalRange.IsAdd)
- AddSpecialLine(hunk.LocalRange.From + 1, ref blankLineOffset, LineState.MergeNoLinesTheirs, OutputTextNoContext, true);
- }
- }
- }
-
- public string GetAllText()
- {
- StringBuilder sb = new StringBuilder();
- foreach (Line line in Lines)
- {
- sb.AppendLine(line.Text);
- }
- return sb.ToString();
- }
-
- private List<string> RemoveLines(Diff3Results.Diff3Hunk hunk, ref int blankLineOffset)
- {
- //mergable lines removed
- Line before = null;
- Line after = null;
- List<string> removedLines = new List<string>();
- int oldBlankLineOffset = blankLineOffset;
- if (hunk.IsDeletion && hunk.LocalRange.From > 0)
- {
- before = Lines[hunk.LocalRange.From + blankLineOffset - 2];
- before.StateBelow = LineState.MergedOkay;
- before.DeletedLines.Below = removedLines;
- }
- for (int line = hunk.LocalRange.From; line <= hunk.LocalRange.To; line++)
- {
- removedLines.Add(Lines[hunk.LocalRange.From + oldBlankLineOffset - 1].Text);
- Lines.RemoveAt(hunk.LocalRange.From + oldBlankLineOffset - 1);
- blankLineOffset--;
- }
- if (hunk.IsDeletion && hunk.LocalRange.To < Lines.Count)
- {
- Lines[hunk.LocalRange.To + blankLineOffset].StateAbove = LineState.MergedOkay;
- after = Lines[hunk.LocalRange.To + blankLineOffset];
- after.DeletedLines.Above = removedLines;
- }
- return removedLines;
- }
-
- private int AddSpecialLine(int lineNo, ref int blankLineOffset, LineState lineState, string text, bool insertOffSetAdj)
- {
- Line builtline = new Line(lineState, text);
- Lines.Insert(lineNo + blankLineOffset - (insertOffSetAdj ? 1 : 0), builtline);
- blankLineOffset++;
- return 1; // no of lines added
- }
-
- public List<ChangeRegion> ChangeRegions;
-
- public int NumberOfMerges = 0;
- public int NumberOfUndoneMerges = 0;
- public int NumberOfConflicts = 0;
- public int NumberOfResolutions = 0;
-
- public class TypedLineCollection
- {
- Dictionary<LineState, List<string>> linesByState = new Dictionary<LineState, List<string>>();
-
- public void AddLine(LineState state, string line)
- {
- if (!linesByState.ContainsKey(state))
- linesByState.Add(state, new List<string>());
-
- linesByState[state].Add(line);
- }
-
- public bool ContainsState(LineState state)
- {
- return linesByState.ContainsKey(state);
- }
-
- public List<string> GetLinesForState(LineState state)
- {
- if (linesByState.ContainsKey(state))
- return linesByState[state];
- else
- return new List<string>();
- }
-
- public int GetCountForState(LineState state)
- {
- if (linesByState.ContainsKey(state))
- return linesByState[state].Count;
- else
- return 0;
- }
- }
-
- public void BuildChangeRegions()
- {
- ResetCounters();
- ChangeRegions = new List<ChangeRegion>();
- int i = 0;
- while (i < Lines.Count)
- {
- bool incDone = false;
- if (Lines[i].State != LineState.None)
- {
- TypedLineCollection lineCol = new TypedLineCollection();
- int start = i;
- while (i < Lines.Count && Lines[i].State != LineState.None)
- {
- lineCol.AddLine(Lines[i].State, Lines[i].Text);
- i++;
- incDone = true;
- }
- ChangeRegion cr = null;
- if (lineCol.GetCountForState(LineState.MergeTheirs) > 0 || lineCol.GetCountForState(LineState.MergeYours) > 0)
- {
- cr = (new ChangeRegion(start, i - 1, lineCol.GetLinesForState(LineState.MergeTheirs), lineCol.GetLinesForState(LineState.MergeYours)));
- NumberOfConflicts++;
- }
- foreach (LineState lineState in new LineState[] { LineState.Resolved, LineState.MergedOkay, LineState.MergeUndone })
- {
- if (lineCol.ContainsState(lineState))
- {
- cr = (new ChangeRegion(start, i - 1, lineCol.GetLinesForState(lineState),
- Lines[start].DeletedLines.Here,
- GetChangeRegionStateFromLineState(lineState),
- ChangeRegionLocation.Here));
- IncrementCounters(lineState);
- }
- }
- //if (cr.MergedText!=null)
- // cr.PreviousText = new List<string>(cr.MergedText);
- ChangeRegions.Add(cr);
- }
-
- if (i >= Lines.Count)
- break;
- // this marks sections that have been deleted with special marks above and below
- if (Lines[i].StateBelow != LineState.None)
- incDone = AddRegionAboveOrBelow(ref i, Lines[i].StateBelow, Lines[i].DeletedLines.Below, ChangeRegionLocation.Below, true);
-
- if (Lines[i].StateAbove != LineState.None)
- incDone = AddRegionAboveOrBelow(ref i, Lines[i].StateAbove, Lines[i].DeletedLines.Above, ChangeRegionLocation.Above, (i == 0));
-
- if (!incDone)
- i++;
- }
- }
-
- private void ResetCounters()
- {
- NumberOfMerges = 0;
- NumberOfUndoneMerges = 0;
- NumberOfConflicts = 0;
- NumberOfResolutions = 0;
- }
-
- private ChangeRegionState GetChangeRegionStateFromLineState(LineState lineState)
- {
- ChangeRegionState crs = ChangeRegionState.None;
- if (lineState == LineState.MergedOkay || lineState == LineState.MergeUndone || lineState == LineState.Resolved)
- crs = (ChangeRegionState)lineState;
- return crs;
- }
-
- private bool AddRegionAboveOrBelow(ref int lineNo, LineState lineState, List<string> deletetedLines, ChangeRegionLocation location, bool incCounter)
- {
- if (incCounter) // if i>0 then this changeregion will have been counted above
- IncrementCounters(lineState);
- ChangeRegionState crs = GetChangeRegionStateFromLineState(lineState);
-
- ChangeRegion cr = (new ChangeRegion(lineNo, lineNo + 1, new List<string>(), deletetedLines, crs, location));
- ChangeRegions.Add(cr);
- lineNo++;
- return true;
- }
-
- private void IncrementCounters(LineState lineState)
- {
- switch (lineState)
- {
- case LineState.MergedOkay:
- NumberOfMerges++;
- break;
- case LineState.Resolved:
- NumberOfResolutions++;
- break;
- case LineState.MergeUndone:
- NumberOfUndoneMerges++;
- break;
- }
- }
-
- public bool ResolveUseX(ChangeRegion changeRegion, bool useTheirs)
- {
- List<string> x = (useTheirs ? changeRegion.TheirLines : changeRegion.YourLines);
- if (changeRegion.State == ChangeRegionState.Conflict)
- {
- for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
- {
- Lines.RemoveAt(changeRegion.Start);
- }
- for (int i = 0; i < x.Count; i++)
- {
- Lines.Insert(changeRegion.Start + i, new Line(LineState.Resolved, x[i], changeRegion.TheirLines, changeRegion.YourLines));
- }
- if (x.Count == 0)
- {
- SetLineResolvedBelow(Lines[changeRegion.Start - 1], changeRegion);
- SetLineResolvedAbove(Lines[changeRegion.Start], changeRegion);
- }
- return true;
- }
- return false;
- }
-
- private void SetLineResolvedBelow(Line line, ChangeRegion conflictRegion)
- {
- line.StateBelow = LineState.Resolved;
- line.ResolvedLines.Theirs.Below = conflictRegion.TheirLines;
- line.ResolvedLines.Yours.Below = conflictRegion.YourLines;
- }
- private void SetLineResolvedAbove(Line line, ChangeRegion conflictRegion)
- {
- line.StateAbove = LineState.Resolved;
- line.ResolvedLines.Theirs.Above = conflictRegion.TheirLines;
- line.ResolvedLines.Yours.Above = conflictRegion.YourLines;
- }
-
- public bool RedoMerge(ChangeRegion changeRegion)
- {
- List<string> deletedLines = new List<string>();
- if (changeRegion.State == ChangeRegionState.UnMerged)
- {
- if (changeRegion.MergedText.Count > 0)
- {
- for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
- {
- deletedLines = Lines[changeRegion.Start].DeletedLines.Here;
- Lines.RemoveAt(changeRegion.Start);
- }
- }
- else
- {
- if (changeRegion.Location == ChangeRegionLocation.Below)
- deletedLines = Lines[changeRegion.Start].DeletedLines.Below;
- else if (changeRegion.Location == ChangeRegionLocation.Above)
- deletedLines = Lines[changeRegion.Start].DeletedLines.Above;
- }
- // I have commented out the reverse op. because it made things go backwards.
- // I guess it needed it before I rewrote a lot of this
- // I've left it in as a reminder of what use to be needed in case I find a scenario
- // that seems to still need it
- // deletedLines.Reverse();
- InsertLinesIntoRegion(changeRegion, LineState.MergedOkay, deletedLines);
-
- if (deletedLines.Count == 0)
- {
- Line line = Lines[changeRegion.Start - 1];
- Lines[changeRegion.Start - 1].StateBelow = LineState.MergedOkay;
- Lines[changeRegion.Start].StateAbove = LineState.MergedOkay;
- }
- else
- {
- if (changeRegion.Location == ChangeRegionLocation.Above)
- {
- Lines[changeRegion.Start - 1].StateBelow = LineState.None;
- Lines[changeRegion.Start + deletedLines.Count].StateAbove = LineState.None;
- }
- if (changeRegion.Location == ChangeRegionLocation.Below)
- {
- Lines[changeRegion.Start].StateBelow = LineState.None;
- Lines[changeRegion.Start + deletedLines.Count + 1].StateAbove = LineState.None;
- }
- }
- return true;
- }
- return false;
- }
-
- public bool UndoMerge(ChangeRegion changeRegion)
- {
-
- List<string> deletedLines = new List<string>();
- if (changeRegion.State == ChangeRegionState.Merged)
- {
- if (changeRegion.MergedText.Count > 0)
- {
- for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
- {
- deletedLines = Lines[changeRegion.Start].DeletedLines.Here;
- Lines.RemoveAt(changeRegion.Start);
- }
- }
- else
- {
- if (changeRegion.Location == ChangeRegionLocation.Below)
- deletedLines = Lines[changeRegion.Start].DeletedLines.Below;
- else if (changeRegion.Location == ChangeRegionLocation.Above)
- deletedLines = Lines[changeRegion.Start].DeletedLines.Above;
- }
- // I have commented out the reverse op. because it made things go backwards.
- // I guess it needed it before I rewrote a lot of this
- // I've left it in as a reminder of what use to be needed in case I find a scenario
- // that seems to still need it
- // deletedLines.Reverse();
- InsertLinesIntoRegion(changeRegion, LineState.MergeUndone, deletedLines);
-
- if (deletedLines.Count == 0)
- {
- Line line = Lines[changeRegion.Start - 1];
- line.StateBelow = LineState.MergeUndone;
- line.DeletedLines.Below = changeRegion.MergedText;
- line = Lines[changeRegion.Start];
- line.StateAbove = LineState.MergeUndone;
- line.DeletedLines.Above = changeRegion.MergedText;
- }
- else
- {
- if (changeRegion.Location == ChangeRegionLocation.Above)
- {
- Lines[changeRegion.Start - 1].StateBelow = LineState.None;
- Lines[changeRegion.Start + deletedLines.Count].StateAbove = LineState.None;
- }
- if (changeRegion.Location == ChangeRegionLocation.Below)
- {
- Lines[changeRegion.Start].StateBelow = LineState.None;
- Lines[changeRegion.Start + deletedLines.Count + 1].StateAbove = LineState.None;
- }
- }
- return true;
- }
- return false;
- }
-
- public bool UndoResolution(ChangeRegion changeRegion)
- {
- List<string> deletedLines = new List<string>();
- List<string> resolvedLinesYours = new List<string>();
- List<string> resolvedLinesTheirs = new List<string>();
- List<string> resolvedLinesMerged = new List<string>();
- if (changeRegion.State == ChangeRegionState.Resolved)
- {
- if (changeRegion.MergedText.Count > 0)
- {
- for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
- {
- resolvedLinesYours = Lines[changeRegion.Start].ResolvedLines.Yours.Here;
- resolvedLinesTheirs = Lines[changeRegion.Start].ResolvedLines.Theirs.Here;
- resolvedLinesMerged = Lines[changeRegion.Start].ResolvedLines.Merged.Here;
- Lines.RemoveAt(changeRegion.Start);
- }
- }
- else
- {
- if (changeRegion.Location == ChangeRegionLocation.Below)
- {
- resolvedLinesYours = Lines[changeRegion.Start].ResolvedLines.Yours.Below;
- resolvedLinesTheirs = Lines[changeRegion.Start].ResolvedLines.Theirs.Below;
- resolvedLinesMerged = Lines[changeRegion.Start].ResolvedLines.Merged.Below;
- }
- else if (changeRegion.Location == ChangeRegionLocation.Above)
- {
- resolvedLinesYours = Lines[changeRegion.Start].ResolvedLines.Yours.Above;
- resolvedLinesTheirs = Lines[changeRegion.Start].ResolvedLines.Theirs.Above;
- resolvedLinesMerged = Lines[changeRegion.Start].ResolvedLines.Merged.Above;
- }
- }
- if (resolvedLinesYours!= null)
- {
- if (resolvedLinesYours.Count == 0)
- InsertLinesIntoRegion(changeRegion, LineState.MergeNoLinesYours, new List<string>(new string[] { "<<No Context Lines>>" }));
-
- InsertLinesIntoRegion(changeRegion, LineState.MergeYours, resolvedLinesYours);
- }
-
- if (resolvedLinesTheirs != null)
- {
- if (resolvedLinesTheirs.Count == 0)
- InsertLinesIntoRegion(changeRegion, LineState.MergeNoLinesTheirs, new List<string>(new string[] { "<<Deleted Range>>" }));
-
- InsertLinesIntoRegion(changeRegion, LineState.MergeTheirs, resolvedLinesTheirs);
- }
-
- if (resolvedLinesMerged != null)
- {
- //if (resolvedLinesMerged.Count == 0)
- // InsertLinesIntoRegion(changeRegion, LineState.MergeNoLinesTheirs, new List<string>(new string[] { "<<Deleted Range>>" }));
-
- if (resolvedLinesMerged.Count != 0)
- InsertLinesIntoRegion(changeRegion, LineState.MergedOkay, resolvedLinesMerged);
- }
-
- if (changeRegion.Location == ChangeRegionLocation.Above)
- {
- Lines[changeRegion.Start - 1].StateBelow = LineState.None;
- Lines[changeRegion.Start + resolvedLinesTheirs.Count + resolvedLinesYours.Count + 1].StateAbove = LineState.None;
- }
- if (changeRegion.Location == ChangeRegionLocation.Below)
- {
- Lines[changeRegion.Start].StateBelow = LineState.None;
- Lines[changeRegion.Start + +resolvedLinesTheirs.Count + resolvedLinesYours.Count + 1].StateAbove = LineState.None;
- }
- return true;
- }
- return false;
- }
-
- private void InsertLinesIntoRegion(ChangeRegion changeRegion, LineState lineState, List<string> lines)
- {
- for (int i = lines.Count - 1; i >= 0; i--)
- {
- Line newLine = new Line(lineState, lines[i]);
- newLine.DeletedLines.Here = changeRegion.MergedText;
- Lines.Insert(changeRegion.Start + ((changeRegion.MergedText.Count == 0 && changeRegion.Location != ChangeRegionLocation.Above) ? 1 : 0), newLine);
- }
-
- }
-
- public void ResolveUseAllYoursOrTheirs(bool useTheirs)
- {
- int offset = 0;
- foreach (ChangeRegion c in ChangeRegions)
- {
- if (c.State == ChangeRegionState.Conflict)
- {
- List<string> lines = (useTheirs ? c.TheirLines : c.YourLines);
- // use a copy of offset, as we'll be modifying the original as we go
- int o = offset;
- for (int i = c.End - c.Start; i >= 0; i--)
- {
- Lines.RemoveAt(c.Start + o);
- offset--;
- }
- for (int i = 0; i < lines.Count; i++)
- {
- Lines.Insert(c.Start + i + o, new Line(LineState.Resolved, lines[i], c.TheirLines, c.YourLines));
- offset++;
- }
- if (lines.Count == 0)
- {
- SetLineResolvedBelow(Lines[c.Start - 1], c);
- SetLineResolvedAbove(Lines[c.Start], c);
- }
- }
- }
- BuildChangeRegions();
- }
-
- public bool ResolveUseNeither(ChangeRegion changeRegion)
- {
- if (changeRegion.State == ChangeRegionState.Conflict)
- {
- for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
- {
- Lines.RemoveAt(changeRegion.Start);
- }
- SetLineResolvedBelow(Lines[changeRegion.Start - 1], changeRegion);
- SetLineResolvedAbove(Lines[changeRegion.Start], changeRegion);
- return true;
- }
- return false;
- }
-
-
-
- public bool ResolveUseOneAfterOther(ChangeRegion changeRegion, bool useMineAfterTheirs)
- {
- if (changeRegion.State == ChangeRegionState.Conflict)
- {
- List<string> before = (useMineAfterTheirs ? changeRegion.TheirLines : changeRegion.YourLines);
- List<string> after = (useMineAfterTheirs ? changeRegion.YourLines : changeRegion.TheirLines);
- for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
- {
- Lines.RemoveAt(changeRegion.Start);
- }
- for (int i = 0; i < before.Count; i++)
- {
- Lines.Insert(changeRegion.Start + i, new Line(LineState.Resolved, before[i], changeRegion.TheirLines, changeRegion.YourLines));
- }
- // this inserts above the previous, which is why it looks backwards
- for (int i = 0; i < after.Count; i++)
- {
- Lines.Insert(changeRegion.Start + i, new Line(LineState.Resolved, after[i], changeRegion.TheirLines, changeRegion.YourLines));
- }
- return true;
- }
- return false;
- }
-
- public bool ResolveUseUserEdit(ChangeRegion changeRegion)
- {
- for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
- {
- Lines.RemoveAt(changeRegion.Start);
- }
- if (changeRegion.EditText.Count > 0)
- {
- for (int i = 0; i < changeRegion.EditText.Count; i++)
- {
- Lines.Insert(changeRegion.Start + i, new Line(LineState.Resolved, changeRegion.EditText[i],
- changeRegion.TheirLines, changeRegion.YourLines, changeRegion.PreviousText));
- }
- }
- else
- {
- SetLineResolvedBelow(Lines[changeRegion.Start - 1], changeRegion);
- SetLineResolvedAbove(Lines[changeRegion.Start], changeRegion);
- }
- return true;
-
- }
- }
- }