PageRenderTime 48ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/diffs/LizardDiff/Diff3Docs/Output.cs

#
C# | 611 lines | 533 code | 57 blank | 21 comment | 123 complexity | 957aa00ee095d4c3ec0d2d65831bffa9 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace Ltf.Diffs.Diff3Docs
  5. {
  6. //nb. synced with / subset of line state
  7. public enum ChangeRegionState
  8. {
  9. None = 0,
  10. Conflict = 10,
  11. Merged = 104,
  12. UnMerged = 105,
  13. Resolved = 106,
  14. UserEdited = 150
  15. }
  16. public enum ChangeRegionLocation
  17. {
  18. Here,
  19. Above,
  20. Below
  21. }
  22. public class ChangeRegion
  23. {
  24. public ChangeRegionState State;
  25. public ChangeRegionLocation Location;
  26. public int Start, End;
  27. public List<string> TheirLines = null;
  28. public List<string> YourLines = null;
  29. public List<string> Resolution = null;
  30. public List<string> MergedText = null;
  31. public List<string> PreviousText = null; // does not appear to be used
  32. public List<string> EditText = null;
  33. public ChangeRegion(int start, int end, List<string> theirs, List<string> yours)
  34. {
  35. this.Start = start;
  36. this.End = end;
  37. TheirLines = theirs;
  38. YourLines = yours;
  39. State = ChangeRegionState.Conflict;
  40. Location = ChangeRegionLocation.Here;
  41. }
  42. public ChangeRegion(int start, int end, List<string> mergedText, List<string> previousText, ChangeRegionState state, ChangeRegionLocation location)
  43. {
  44. this.Start = start;
  45. this.End = end;
  46. MergedText = mergedText;
  47. PreviousText = previousText;
  48. State = state;
  49. Location = location;
  50. }
  51. }
  52. public class Output : DiffDocument
  53. {
  54. const string OutputTextRangeDeleted = "<< Range Deleted >>";
  55. const string OutputTextNoContext = "<< No matching context >>";
  56. public Output(string fileName)
  57. : base(fileName) { }
  58. public override void LoadResults(Diff3Results results)
  59. {
  60. // showing base and server changes - added lines to keep in sync with local
  61. // main file based on server file.
  62. int blankLineOffset = 0;
  63. foreach (Diff3Results.Diff3Hunk hunk in results.Hunks)
  64. {
  65. bool insertOffSetAdj = hunk.LocalRange.IsAdd ? false : true;
  66. LineState insertLineState = hunk.IsAllDiff ? LineState.MergeTheirs : LineState.MergedOkay;
  67. LineState markLineState = LineState.MergeYours;
  68. int extraOffset = 0;
  69. List<string> removedLines = new List<string>();
  70. if (hunk.IsAllDiff && hunk.ServerRange.IsAdd)
  71. AddSpecialLine(hunk.LocalRange.From, ref blankLineOffset, LineState.MergeNoLinesTheirs, OutputTextRangeDeleted, true);
  72. if (hunk.IsAllDiff || hunk.IsServerDiff)
  73. {
  74. if (hunk.IsServerDiff && !hunk.LocalRange.IsAdd)
  75. {
  76. removedLines = RemoveLines(hunk, ref blankLineOffset);
  77. extraOffset = hunk.LocalRange.Interval;
  78. }
  79. if (!hunk.ServerRange.IsAdd)
  80. InsertChanges(hunk.LocalRange.From, insertLineState, hunk.ServerLines, ref blankLineOffset, insertOffSetAdj, extraOffset, removedLines);
  81. }
  82. if (hunk.IsAllDiff)
  83. {
  84. if (!hunk.LocalRange.IsAdd)
  85. MarkChanges(hunk.LocalRange.From, markLineState, hunk.LocalRange.Interval, blankLineOffset, true);
  86. if (hunk.LocalRange.IsAdd)
  87. AddSpecialLine(hunk.LocalRange.From + 1, ref blankLineOffset, LineState.MergeNoLinesTheirs, OutputTextNoContext, true);
  88. }
  89. }
  90. }
  91. public string GetAllText()
  92. {
  93. StringBuilder sb = new StringBuilder();
  94. foreach (Line line in Lines)
  95. {
  96. sb.AppendLine(line.Text);
  97. }
  98. return sb.ToString();
  99. }
  100. private List<string> RemoveLines(Diff3Results.Diff3Hunk hunk, ref int blankLineOffset)
  101. {
  102. //mergable lines removed
  103. Line before = null;
  104. Line after = null;
  105. List<string> removedLines = new List<string>();
  106. int oldBlankLineOffset = blankLineOffset;
  107. if (hunk.IsDeletion && hunk.LocalRange.From > 0)
  108. {
  109. before = Lines[hunk.LocalRange.From + blankLineOffset - 2];
  110. before.StateBelow = LineState.MergedOkay;
  111. before.DeletedLines.Below = removedLines;
  112. }
  113. for (int line = hunk.LocalRange.From; line <= hunk.LocalRange.To; line++)
  114. {
  115. removedLines.Add(Lines[hunk.LocalRange.From + oldBlankLineOffset - 1].Text);
  116. Lines.RemoveAt(hunk.LocalRange.From + oldBlankLineOffset - 1);
  117. blankLineOffset--;
  118. }
  119. if (hunk.IsDeletion && hunk.LocalRange.To < Lines.Count)
  120. {
  121. Lines[hunk.LocalRange.To + blankLineOffset].StateAbove = LineState.MergedOkay;
  122. after = Lines[hunk.LocalRange.To + blankLineOffset];
  123. after.DeletedLines.Above = removedLines;
  124. }
  125. return removedLines;
  126. }
  127. private int AddSpecialLine(int lineNo, ref int blankLineOffset, LineState lineState, string text, bool insertOffSetAdj)
  128. {
  129. Line builtline = new Line(lineState, text);
  130. Lines.Insert(lineNo + blankLineOffset - (insertOffSetAdj ? 1 : 0), builtline);
  131. blankLineOffset++;
  132. return 1; // no of lines added
  133. }
  134. public List<ChangeRegion> ChangeRegions;
  135. public int NumberOfMerges = 0;
  136. public int NumberOfUndoneMerges = 0;
  137. public int NumberOfConflicts = 0;
  138. public int NumberOfResolutions = 0;
  139. public class TypedLineCollection
  140. {
  141. Dictionary<LineState, List<string>> linesByState = new Dictionary<LineState, List<string>>();
  142. public void AddLine(LineState state, string line)
  143. {
  144. if (!linesByState.ContainsKey(state))
  145. linesByState.Add(state, new List<string>());
  146. linesByState[state].Add(line);
  147. }
  148. public bool ContainsState(LineState state)
  149. {
  150. return linesByState.ContainsKey(state);
  151. }
  152. public List<string> GetLinesForState(LineState state)
  153. {
  154. if (linesByState.ContainsKey(state))
  155. return linesByState[state];
  156. else
  157. return new List<string>();
  158. }
  159. public int GetCountForState(LineState state)
  160. {
  161. if (linesByState.ContainsKey(state))
  162. return linesByState[state].Count;
  163. else
  164. return 0;
  165. }
  166. }
  167. public void BuildChangeRegions()
  168. {
  169. ResetCounters();
  170. ChangeRegions = new List<ChangeRegion>();
  171. int i = 0;
  172. while (i < Lines.Count)
  173. {
  174. bool incDone = false;
  175. if (Lines[i].State != LineState.None)
  176. {
  177. TypedLineCollection lineCol = new TypedLineCollection();
  178. int start = i;
  179. while (i < Lines.Count && Lines[i].State != LineState.None)
  180. {
  181. lineCol.AddLine(Lines[i].State, Lines[i].Text);
  182. i++;
  183. incDone = true;
  184. }
  185. ChangeRegion cr = null;
  186. if (lineCol.GetCountForState(LineState.MergeTheirs) > 0 || lineCol.GetCountForState(LineState.MergeYours) > 0)
  187. {
  188. cr = (new ChangeRegion(start, i - 1, lineCol.GetLinesForState(LineState.MergeTheirs), lineCol.GetLinesForState(LineState.MergeYours)));
  189. NumberOfConflicts++;
  190. }
  191. foreach (LineState lineState in new LineState[] { LineState.Resolved, LineState.MergedOkay, LineState.MergeUndone })
  192. {
  193. if (lineCol.ContainsState(lineState))
  194. {
  195. cr = (new ChangeRegion(start, i - 1, lineCol.GetLinesForState(lineState),
  196. Lines[start].DeletedLines.Here,
  197. GetChangeRegionStateFromLineState(lineState),
  198. ChangeRegionLocation.Here));
  199. IncrementCounters(lineState);
  200. }
  201. }
  202. //if (cr.MergedText!=null)
  203. // cr.PreviousText = new List<string>(cr.MergedText);
  204. ChangeRegions.Add(cr);
  205. }
  206. if (i >= Lines.Count)
  207. break;
  208. // this marks sections that have been deleted with special marks above and below
  209. if (Lines[i].StateBelow != LineState.None)
  210. incDone = AddRegionAboveOrBelow(ref i, Lines[i].StateBelow, Lines[i].DeletedLines.Below, ChangeRegionLocation.Below, true);
  211. if (Lines[i].StateAbove != LineState.None)
  212. incDone = AddRegionAboveOrBelow(ref i, Lines[i].StateAbove, Lines[i].DeletedLines.Above, ChangeRegionLocation.Above, (i == 0));
  213. if (!incDone)
  214. i++;
  215. }
  216. }
  217. private void ResetCounters()
  218. {
  219. NumberOfMerges = 0;
  220. NumberOfUndoneMerges = 0;
  221. NumberOfConflicts = 0;
  222. NumberOfResolutions = 0;
  223. }
  224. private ChangeRegionState GetChangeRegionStateFromLineState(LineState lineState)
  225. {
  226. ChangeRegionState crs = ChangeRegionState.None;
  227. if (lineState == LineState.MergedOkay || lineState == LineState.MergeUndone || lineState == LineState.Resolved)
  228. crs = (ChangeRegionState)lineState;
  229. return crs;
  230. }
  231. private bool AddRegionAboveOrBelow(ref int lineNo, LineState lineState, List<string> deletetedLines, ChangeRegionLocation location, bool incCounter)
  232. {
  233. if (incCounter) // if i>0 then this changeregion will have been counted above
  234. IncrementCounters(lineState);
  235. ChangeRegionState crs = GetChangeRegionStateFromLineState(lineState);
  236. ChangeRegion cr = (new ChangeRegion(lineNo, lineNo + 1, new List<string>(), deletetedLines, crs, location));
  237. ChangeRegions.Add(cr);
  238. lineNo++;
  239. return true;
  240. }
  241. private void IncrementCounters(LineState lineState)
  242. {
  243. switch (lineState)
  244. {
  245. case LineState.MergedOkay:
  246. NumberOfMerges++;
  247. break;
  248. case LineState.Resolved:
  249. NumberOfResolutions++;
  250. break;
  251. case LineState.MergeUndone:
  252. NumberOfUndoneMerges++;
  253. break;
  254. }
  255. }
  256. public bool ResolveUseX(ChangeRegion changeRegion, bool useTheirs)
  257. {
  258. List<string> x = (useTheirs ? changeRegion.TheirLines : changeRegion.YourLines);
  259. if (changeRegion.State == ChangeRegionState.Conflict)
  260. {
  261. for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
  262. {
  263. Lines.RemoveAt(changeRegion.Start);
  264. }
  265. for (int i = 0; i < x.Count; i++)
  266. {
  267. Lines.Insert(changeRegion.Start + i, new Line(LineState.Resolved, x[i], changeRegion.TheirLines, changeRegion.YourLines));
  268. }
  269. if (x.Count == 0)
  270. {
  271. SetLineResolvedBelow(Lines[changeRegion.Start - 1], changeRegion);
  272. SetLineResolvedAbove(Lines[changeRegion.Start], changeRegion);
  273. }
  274. return true;
  275. }
  276. return false;
  277. }
  278. private void SetLineResolvedBelow(Line line, ChangeRegion conflictRegion)
  279. {
  280. line.StateBelow = LineState.Resolved;
  281. line.ResolvedLines.Theirs.Below = conflictRegion.TheirLines;
  282. line.ResolvedLines.Yours.Below = conflictRegion.YourLines;
  283. }
  284. private void SetLineResolvedAbove(Line line, ChangeRegion conflictRegion)
  285. {
  286. line.StateAbove = LineState.Resolved;
  287. line.ResolvedLines.Theirs.Above = conflictRegion.TheirLines;
  288. line.ResolvedLines.Yours.Above = conflictRegion.YourLines;
  289. }
  290. public bool RedoMerge(ChangeRegion changeRegion)
  291. {
  292. List<string> deletedLines = new List<string>();
  293. if (changeRegion.State == ChangeRegionState.UnMerged)
  294. {
  295. if (changeRegion.MergedText.Count > 0)
  296. {
  297. for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
  298. {
  299. deletedLines = Lines[changeRegion.Start].DeletedLines.Here;
  300. Lines.RemoveAt(changeRegion.Start);
  301. }
  302. }
  303. else
  304. {
  305. if (changeRegion.Location == ChangeRegionLocation.Below)
  306. deletedLines = Lines[changeRegion.Start].DeletedLines.Below;
  307. else if (changeRegion.Location == ChangeRegionLocation.Above)
  308. deletedLines = Lines[changeRegion.Start].DeletedLines.Above;
  309. }
  310. // I have commented out the reverse op. because it made things go backwards.
  311. // I guess it needed it before I rewrote a lot of this
  312. // I've left it in as a reminder of what use to be needed in case I find a scenario
  313. // that seems to still need it
  314. // deletedLines.Reverse();
  315. InsertLinesIntoRegion(changeRegion, LineState.MergedOkay, deletedLines);
  316. if (deletedLines.Count == 0)
  317. {
  318. Line line = Lines[changeRegion.Start - 1];
  319. Lines[changeRegion.Start - 1].StateBelow = LineState.MergedOkay;
  320. Lines[changeRegion.Start].StateAbove = LineState.MergedOkay;
  321. }
  322. else
  323. {
  324. if (changeRegion.Location == ChangeRegionLocation.Above)
  325. {
  326. Lines[changeRegion.Start - 1].StateBelow = LineState.None;
  327. Lines[changeRegion.Start + deletedLines.Count].StateAbove = LineState.None;
  328. }
  329. if (changeRegion.Location == ChangeRegionLocation.Below)
  330. {
  331. Lines[changeRegion.Start].StateBelow = LineState.None;
  332. Lines[changeRegion.Start + deletedLines.Count + 1].StateAbove = LineState.None;
  333. }
  334. }
  335. return true;
  336. }
  337. return false;
  338. }
  339. public bool UndoMerge(ChangeRegion changeRegion)
  340. {
  341. List<string> deletedLines = new List<string>();
  342. if (changeRegion.State == ChangeRegionState.Merged)
  343. {
  344. if (changeRegion.MergedText.Count > 0)
  345. {
  346. for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
  347. {
  348. deletedLines = Lines[changeRegion.Start].DeletedLines.Here;
  349. Lines.RemoveAt(changeRegion.Start);
  350. }
  351. }
  352. else
  353. {
  354. if (changeRegion.Location == ChangeRegionLocation.Below)
  355. deletedLines = Lines[changeRegion.Start].DeletedLines.Below;
  356. else if (changeRegion.Location == ChangeRegionLocation.Above)
  357. deletedLines = Lines[changeRegion.Start].DeletedLines.Above;
  358. }
  359. // I have commented out the reverse op. because it made things go backwards.
  360. // I guess it needed it before I rewrote a lot of this
  361. // I've left it in as a reminder of what use to be needed in case I find a scenario
  362. // that seems to still need it
  363. // deletedLines.Reverse();
  364. InsertLinesIntoRegion(changeRegion, LineState.MergeUndone, deletedLines);
  365. if (deletedLines.Count == 0)
  366. {
  367. Line line = Lines[changeRegion.Start - 1];
  368. line.StateBelow = LineState.MergeUndone;
  369. line.DeletedLines.Below = changeRegion.MergedText;
  370. line = Lines[changeRegion.Start];
  371. line.StateAbove = LineState.MergeUndone;
  372. line.DeletedLines.Above = changeRegion.MergedText;
  373. }
  374. else
  375. {
  376. if (changeRegion.Location == ChangeRegionLocation.Above)
  377. {
  378. Lines[changeRegion.Start - 1].StateBelow = LineState.None;
  379. Lines[changeRegion.Start + deletedLines.Count].StateAbove = LineState.None;
  380. }
  381. if (changeRegion.Location == ChangeRegionLocation.Below)
  382. {
  383. Lines[changeRegion.Start].StateBelow = LineState.None;
  384. Lines[changeRegion.Start + deletedLines.Count + 1].StateAbove = LineState.None;
  385. }
  386. }
  387. return true;
  388. }
  389. return false;
  390. }
  391. public bool UndoResolution(ChangeRegion changeRegion)
  392. {
  393. List<string> deletedLines = new List<string>();
  394. List<string> resolvedLinesYours = new List<string>();
  395. List<string> resolvedLinesTheirs = new List<string>();
  396. List<string> resolvedLinesMerged = new List<string>();
  397. if (changeRegion.State == ChangeRegionState.Resolved)
  398. {
  399. if (changeRegion.MergedText.Count > 0)
  400. {
  401. for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
  402. {
  403. resolvedLinesYours = Lines[changeRegion.Start].ResolvedLines.Yours.Here;
  404. resolvedLinesTheirs = Lines[changeRegion.Start].ResolvedLines.Theirs.Here;
  405. resolvedLinesMerged = Lines[changeRegion.Start].ResolvedLines.Merged.Here;
  406. Lines.RemoveAt(changeRegion.Start);
  407. }
  408. }
  409. else
  410. {
  411. if (changeRegion.Location == ChangeRegionLocation.Below)
  412. {
  413. resolvedLinesYours = Lines[changeRegion.Start].ResolvedLines.Yours.Below;
  414. resolvedLinesTheirs = Lines[changeRegion.Start].ResolvedLines.Theirs.Below;
  415. resolvedLinesMerged = Lines[changeRegion.Start].ResolvedLines.Merged.Below;
  416. }
  417. else if (changeRegion.Location == ChangeRegionLocation.Above)
  418. {
  419. resolvedLinesYours = Lines[changeRegion.Start].ResolvedLines.Yours.Above;
  420. resolvedLinesTheirs = Lines[changeRegion.Start].ResolvedLines.Theirs.Above;
  421. resolvedLinesMerged = Lines[changeRegion.Start].ResolvedLines.Merged.Above;
  422. }
  423. }
  424. if (resolvedLinesYours!= null)
  425. {
  426. if (resolvedLinesYours.Count == 0)
  427. InsertLinesIntoRegion(changeRegion, LineState.MergeNoLinesYours, new List<string>(new string[] { "<<No Context Lines>>" }));
  428. InsertLinesIntoRegion(changeRegion, LineState.MergeYours, resolvedLinesYours);
  429. }
  430. if (resolvedLinesTheirs != null)
  431. {
  432. if (resolvedLinesTheirs.Count == 0)
  433. InsertLinesIntoRegion(changeRegion, LineState.MergeNoLinesTheirs, new List<string>(new string[] { "<<Deleted Range>>" }));
  434. InsertLinesIntoRegion(changeRegion, LineState.MergeTheirs, resolvedLinesTheirs);
  435. }
  436. if (resolvedLinesMerged != null)
  437. {
  438. //if (resolvedLinesMerged.Count == 0)
  439. // InsertLinesIntoRegion(changeRegion, LineState.MergeNoLinesTheirs, new List<string>(new string[] { "<<Deleted Range>>" }));
  440. if (resolvedLinesMerged.Count != 0)
  441. InsertLinesIntoRegion(changeRegion, LineState.MergedOkay, resolvedLinesMerged);
  442. }
  443. if (changeRegion.Location == ChangeRegionLocation.Above)
  444. {
  445. Lines[changeRegion.Start - 1].StateBelow = LineState.None;
  446. Lines[changeRegion.Start + resolvedLinesTheirs.Count + resolvedLinesYours.Count + 1].StateAbove = LineState.None;
  447. }
  448. if (changeRegion.Location == ChangeRegionLocation.Below)
  449. {
  450. Lines[changeRegion.Start].StateBelow = LineState.None;
  451. Lines[changeRegion.Start + +resolvedLinesTheirs.Count + resolvedLinesYours.Count + 1].StateAbove = LineState.None;
  452. }
  453. return true;
  454. }
  455. return false;
  456. }
  457. private void InsertLinesIntoRegion(ChangeRegion changeRegion, LineState lineState, List<string> lines)
  458. {
  459. for (int i = lines.Count - 1; i >= 0; i--)
  460. {
  461. Line newLine = new Line(lineState, lines[i]);
  462. newLine.DeletedLines.Here = changeRegion.MergedText;
  463. Lines.Insert(changeRegion.Start + ((changeRegion.MergedText.Count == 0 && changeRegion.Location != ChangeRegionLocation.Above) ? 1 : 0), newLine);
  464. }
  465. }
  466. public void ResolveUseAllYoursOrTheirs(bool useTheirs)
  467. {
  468. int offset = 0;
  469. foreach (ChangeRegion c in ChangeRegions)
  470. {
  471. if (c.State == ChangeRegionState.Conflict)
  472. {
  473. List<string> lines = (useTheirs ? c.TheirLines : c.YourLines);
  474. // use a copy of offset, as we'll be modifying the original as we go
  475. int o = offset;
  476. for (int i = c.End - c.Start; i >= 0; i--)
  477. {
  478. Lines.RemoveAt(c.Start + o);
  479. offset--;
  480. }
  481. for (int i = 0; i < lines.Count; i++)
  482. {
  483. Lines.Insert(c.Start + i + o, new Line(LineState.Resolved, lines[i], c.TheirLines, c.YourLines));
  484. offset++;
  485. }
  486. if (lines.Count == 0)
  487. {
  488. SetLineResolvedBelow(Lines[c.Start - 1], c);
  489. SetLineResolvedAbove(Lines[c.Start], c);
  490. }
  491. }
  492. }
  493. BuildChangeRegions();
  494. }
  495. public bool ResolveUseNeither(ChangeRegion changeRegion)
  496. {
  497. if (changeRegion.State == ChangeRegionState.Conflict)
  498. {
  499. for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
  500. {
  501. Lines.RemoveAt(changeRegion.Start);
  502. }
  503. SetLineResolvedBelow(Lines[changeRegion.Start - 1], changeRegion);
  504. SetLineResolvedAbove(Lines[changeRegion.Start], changeRegion);
  505. return true;
  506. }
  507. return false;
  508. }
  509. public bool ResolveUseOneAfterOther(ChangeRegion changeRegion, bool useMineAfterTheirs)
  510. {
  511. if (changeRegion.State == ChangeRegionState.Conflict)
  512. {
  513. List<string> before = (useMineAfterTheirs ? changeRegion.TheirLines : changeRegion.YourLines);
  514. List<string> after = (useMineAfterTheirs ? changeRegion.YourLines : changeRegion.TheirLines);
  515. for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
  516. {
  517. Lines.RemoveAt(changeRegion.Start);
  518. }
  519. for (int i = 0; i < before.Count; i++)
  520. {
  521. Lines.Insert(changeRegion.Start + i, new Line(LineState.Resolved, before[i], changeRegion.TheirLines, changeRegion.YourLines));
  522. }
  523. // this inserts above the previous, which is why it looks backwards
  524. for (int i = 0; i < after.Count; i++)
  525. {
  526. Lines.Insert(changeRegion.Start + i, new Line(LineState.Resolved, after[i], changeRegion.TheirLines, changeRegion.YourLines));
  527. }
  528. return true;
  529. }
  530. return false;
  531. }
  532. public bool ResolveUseUserEdit(ChangeRegion changeRegion)
  533. {
  534. for (int i = changeRegion.End - changeRegion.Start; i >= 0; i--)
  535. {
  536. Lines.RemoveAt(changeRegion.Start);
  537. }
  538. if (changeRegion.EditText.Count > 0)
  539. {
  540. for (int i = 0; i < changeRegion.EditText.Count; i++)
  541. {
  542. Lines.Insert(changeRegion.Start + i, new Line(LineState.Resolved, changeRegion.EditText[i],
  543. changeRegion.TheirLines, changeRegion.YourLines, changeRegion.PreviousText));
  544. }
  545. }
  546. else
  547. {
  548. SetLineResolvedBelow(Lines[changeRegion.Start - 1], changeRegion);
  549. SetLineResolvedAbove(Lines[changeRegion.Start], changeRegion);
  550. }
  551. return true;
  552. }
  553. }
  554. }