public void The_merged_file_needs_careful_testing() { // inputs string fileBodyLeft = Helper.GetResource(resourcePrefix + "MultiDiffs_Left.txt"); string fileBodyRight = Helper.GetResource(resourcePrefix + "MultiDiffs_Right.txt"); string fileExpected = Helper.GetResource(resourcePrefix + "MultiDiffs_Expected.txt"); TypeOfDiff typeOfDiff = SlyceMerge.PerformTwoWayDiff(identifyConflictsAndRegions, fileBodyLeft, fileBodyRight, out leftConflictLines, out rightConflictLines, out mergedText); Assert.AreEqual(TypeOfDiff.Conflict, typeOfDiff, "TypeOfDiffs are different."); Assert.AreEqual(fileExpected.Trim(), mergedText.Trim(), "Combined file should equal expected file."); int leftConflictLinesMax = leftConflictLines.GetUpperBound(0); Assert.AreEqual(7, leftConflictLinesMax, "Should be 8 left lines in conflict."); int rightConflictLinesMax = rightConflictLines.GetUpperBound(0); Assert.AreEqual(7, rightConflictLinesMax, "Should be 8 right lines in conflict."); Assert.AreEqual(0, leftConflictLines[0].StartLine, "Left conflict lines should start at line 1 (index 0)."); Assert.AreEqual(23, leftConflictLines[leftConflictLinesMax].StartLine, "Last left conflict line should start at line 24 (index 23)."); Assert.AreEqual(2, rightConflictLines[0].StartLine, "Right conflict lines should start at line 3 (index 2)."); Assert.AreEqual(25, rightConflictLines[rightConflictLinesMax].EndLine, "Last right conflict lines should start at line 26 (index 25)."); }
public void Cannot_merge_Mark_as_a_conflict() { string userText = Helper.GetResource(resourcePrefix + "ThreeOtherLines2.txt"); string prevGenText = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string newGenText = Helper.GetResource(resourcePrefix + "ThreeOtherLines.txt"); SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(TypeOfDiff.Conflict, mergeObject.DiffType, "Cannot merge. Mark as conflicted."); }
public void The_merged_equals_3CrLfs_input() { string userText = Environment.NewLine + Environment.NewLine + Environment.NewLine; string prevGenText = userText; string newGenText = userText; SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(TypeOfDiff.ExactCopy, mergeObject.DiffType, "Mark as Exact Copy."); Assert.AreEqual(userText, merged, "The merged text should equal the 3 empty lines."); }
public void First_line_changed_Go_with_the_User_version() { string userText = Helper.GetResource(resourcePrefix + "ThreeLines_FirstLineDeleted.txt"); string prevGenText = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string newGenText = Helper.GetResource(resourcePrefix + "ThreeLines_FirstLineChanged.txt"); string fileExpected = userText; SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(TypeOfDiff.Conflict, mergeObject.DiffType, "Cannot merge. Mark as conflicted."); }
public void Last_line_changed_Cannot_merge_Mark_as_a_conflict() { string userText = Helper.GetResource(resourcePrefix + "ThreeLines_LastLineChanged.txt"); string prevGenText = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string newGenText = Helper.GetResource(resourcePrefix + "TwoLines.txt"); string fileExpected = userText; SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(TypeOfDiff.Conflict, mergeObject.DiffType, "Cannot merge. Mark as conflicted."); }
public void Even_when_all_files_are_empty() { string userText = string.Empty; string prevGenText = userText; string newGenText = userText; SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(String.Empty, merged, "The merged text should be empty."); Assert.AreEqual(TypeOfDiff.ExactCopy, mergeObject.DiffType, "Mark as Exact Copy."); }
public void The_merged_file_equals_the_NewGen_TEMPLATECHANGE() { string userText = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string prevGenText = userText; string newGenText = Helper.GetResource(resourcePrefix + "ThreeOtherLines.txt"); SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(TypeOfDiff.TemplateChangeOnly, mergeObject.DiffType, "Mark as Exact Copy."); Assert.AreEqual(newGenText, merged, "Merged file should equal NewGen."); }
public void The_merged_file_equals_2way_merge_of_User_and_NewGen_CONFLICT() { string userText = Helper.GetResource(resourcePrefix + "FourLines.txt"); string prevGenText = string.Empty; string newGenText = Helper.GetResource(resourcePrefix + "FourLines_2Different.txt"); string fileExpected = Helper.GetResource(resourcePrefix + "FourLines_Expected.txt"); SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(TypeOfDiff.Conflict, mergeObject.DiffType, "Mark as Exact Copy."); Assert.AreEqual(fileExpected, merged, "Merged file should equal merge of User and NewGen."); }
public void The_merged_file_equals_User_and_NewGen() { string userText = Helper.GetResource(resourcePrefix + "TwoLinesWithEmptyLines.txt"); string prevGenText = string.Empty; string newGenText = userText; string fileExpected = userText; SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(TypeOfDiff.ExactCopy, mergeObject.DiffType, "Mark as Exact Copy."); Assert.AreEqual(fileExpected, merged, "Merged file should equal User and NewGen."); }
public void The_merged_equals_the_simple_input_with_linebreaks() { string userText = Helper.GetResource(resourcePrefix + "TwoLinesWithEmptyLines.txt"); string prevGenText = userText; string newGenText = userText; string fileExpected = userText; SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(TypeOfDiff.ExactCopy, mergeObject.DiffType, "Mark as Exact Copy."); Assert.AreEqual(fileExpected, merged, "The merged text should equal the input."); }
public void To_NewGen_line1_Include_it() { string prevGenText = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string userText = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string newGenText = Helper.GetResource(resourcePrefix + "ThreeLines_LastLineChanged.txt"); string fileExpected = newGenText; SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(TypeOfDiff.TemplateChangeOnly, mergeObject.DiffType, "NewGen change only."); Assert.AreEqual(fileExpected, merged, "NewGen change incorporated."); }
public void Same_first_line_added_to_User_and_NewGen_Include_it() { string prevGenText = Helper.GetResource(resourcePrefix + "ThreeLines_FirstLineDeleted.txt"); string userText = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string newGenText = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string fileExpected = userText; SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(TypeOfDiff.ExactCopy, mergeObject.DiffType, "Same changes to both files."); Assert.AreEqual(fileExpected, merged, "User change incorporated."); }
public void Last_line_inserted_in_User_Include_it() { string prevGenText = Helper.GetResource(resourcePrefix + "TwoLines.txt"); string userText = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string newGenText = Helper.GetResource(resourcePrefix + "TwoLines.txt"); string fileExpected = userText; SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(TypeOfDiff.UserChangeOnly, mergeObject.DiffType, "User change only."); Assert.AreEqual(fileExpected, merged, "User change incorporated."); }
public void From_User_remove_from_merge() { string userText = Helper.GetResource(resourcePrefix + "ThreeLines_FirstLineDeleted.txt"); string prevGenText = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string newGenText = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string fileExpected = userText; SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(TypeOfDiff.UserChangeOnly, mergeObject.DiffType, "User change only."); Assert.AreEqual(fileExpected, merged, "User supercedes unchanged NewGen."); }
public void User_changes_merge_with_unchanged_NewGen() { string userText = Helper.GetResource(resourcePrefix + "ThreeOtherLines.txt"); string prevGenText = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string newGenText = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string fileExpected = userText; SlyceMergeResult mergeObject = SlyceMerge.Perform3wayDiff(userText, prevGenText, newGenText, out merged); Assert.AreEqual(TypeOfDiff.UserChangeOnly, mergeObject.DiffType, "User change only."); Assert.AreEqual(fileExpected, merged, "NewGen supercedes unchanged user."); }
/// <summary> /// Diffs two files and displays the diffed content in a single SyntaxEditor. /// </summary> /// <param name="editor"></param> /// <param name="fileBodyLeft"></param> /// <param name="fileBodyRight"></param> /// <param name="strikeoutRightLines"></param> /// <returns></returns> public static bool Perform2WayDiffInSingleEditor( ActiproSoftware.SyntaxEditor.SyntaxEditor editor, ref string fileBodyLeft, ref string fileBodyRight, bool strikeoutRightLines) { string combinedText; SlyceMerge.LineSpan[] userLines; SlyceMerge.LineSpan[] templateLines; SlyceMerge.PerformTwoWayDiff(false, fileBodyLeft, fileBodyRight, out userLines, out templateLines, out combinedText); PopulateSyntaxEditor(editor, combinedText, userLines, templateLines, strikeoutRightLines); bool filesTheSame = userLines.Length == 0 && templateLines.Length == 0; return(filesTheSame); }
/// <summary> /// Performs a Diff between two strings and displays them in two SyntaxEditors with offset coloured lines. /// </summary> /// <param name="editorLeft"></param> /// <param name="editorRight"></param> /// <param name="fileBodyLeft"></param> /// <param name="fileBodyRight"></param> /// <returns></returns> public static bool Perform2WayDiffInTwoEditors( ActiproSoftware.SyntaxEditor.SyntaxEditor editorLeft, ActiproSoftware.SyntaxEditor.SyntaxEditor editorRight, ref string fileBodyLeft, ref string fileBodyRight) { string combinedText; SlyceMerge.LineSpan[] userLines; SlyceMerge.LineSpan[] templateLines; SlyceMerge.PerformTwoWayDiff(false, fileBodyLeft, fileBodyRight, out userLines, out templateLines, out combinedText); Slyce.IntelliMerge.UI.Utility.PopulateSyntaxEditors(editorLeft, editorRight, combinedText, userLines, templateLines); bool filesTheSame = userLines.Length == 0 && templateLines.Length == 0; return(filesTheSame); }
private void ProcessConflict(Merge.Conflict conflict) { string[] userLines = SlyceMerge.GetLinesFromRange(user, conflict.Ranges[Merge.UserIndex]); string[] newgenLines = SlyceMerge.GetLinesFromRange(newgen, conflict.Ranges[Merge.NewGenIndex]); if (userLines.Length == 0 && newgenLines.Length == 0) { // user and template have both deleted some lines. Add them in as virtual lines. foreach (string line in SlyceMerge.GetLinesFromRange(prevgen, conflict.Ranges[Merge.PrevGenIndex])) { vdo.AddLineToLeft(line, ChangeType.UserAndTemplate); } return; } Diff diff = new Diff(userLines, newgenLines, true, true); foreach (Diff.Hunk hunk in diff) { if (hunk.Same) { foreach (string line in hunk.Original()) { vdo.AddLine(line, ChangeType.None); } continue; } // Conflict VisualDiffOutput.ConflictRange crange = new VisualDiffOutput.ConflictRange(); crange.StartLineIndex = vdo.LeftLines.Count; for (int i = hunk.Left.Start; i <= hunk.Left.End; i++) { vdo.LeftLines.Add(new DiffLine(userLines[i], ChangeType.User)); vdo.RightLines.Add(new DiffLine("", ChangeType.User, true)); } for (int i = hunk.Right.Start; i <= hunk.Right.End; i++) { vdo.LeftLines.Add(new DiffLine(newgenLines[i], ChangeType.Template)); vdo.RightLines.Add(new DiffLine("", ChangeType.Template, true)); } crange.EndLineIndex = vdo.LeftLines.Count; vdo.ConflictRanges.Add(crange); vdo.DiffType = TypeOfDiff.Conflict; } }
public void The_merged_file_equals_the_nonempty_file() { // inputs (test opposite order) string fileBodyLeft = string.Empty; string fileBodyRight = File.ReadAllText(@"..\..\Notes.txt"); TypeOfDiff typeOfDiff = SlyceMerge.PerformTwoWayDiff(identifyConflictsAndRegions, fileBodyLeft, fileBodyRight, out leftConflictLines, out rightConflictLines, out mergedText); Assert.AreEqual(TypeOfDiff.Warning, typeOfDiff, "TypeOfDiffs are different."); Assert.AreEqual(-1, leftConflictLines.GetUpperBound(0), "Left conflict lines should be > zero."); Assert.AreEqual(0, rightConflictLines.GetUpperBound(0), "Right conflict lines should be zero."); Assert.AreEqual(fileBodyRight.Trim(), mergedText.Trim(), "Merged text should equal start text."); }
public void The_merged_file_equals_the_left_file() { // inputs string fileBodyLeft = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string fileBodyRight = Helper.GetResource(resourcePrefix + "TwoLines.txt"); TypeOfDiff typeOfDiff = SlyceMerge.PerformTwoWayDiff(identifyConflictsAndRegions, fileBodyLeft, fileBodyRight, out leftConflictLines, out rightConflictLines, out mergedText); Assert.AreEqual(TypeOfDiff.Warning, typeOfDiff, "TypeOfDiffs are different."); Assert.AreEqual(0, leftConflictLines.GetUpperBound(0), "Left conflict lines should be zero."); Assert.AreEqual(-1, rightConflictLines.GetUpperBound(0), "Right conflict lines should be > zero."); Assert.AreEqual(fileBodyLeft.Trim(), mergedText.Trim(), "Left file should equal combined file."); }
public void The_merged_file_is_empty() { // inputs string fileBodyLeft = string.Empty; string fileBodyRight = string.Empty; TypeOfDiff typeOfDiff = SlyceMerge.PerformTwoWayDiff(identifyConflictsOnly, fileBodyLeft, fileBodyRight, out leftConflictLines, out rightConflictLines, out mergedText); Assert.AreEqual(TypeOfDiff.ExactCopy, typeOfDiff, "TypeOfDiffs are different."); Assert.AreEqual(-1, leftConflictLines.GetUpperBound(0), "Left conflict lines should be zero."); Assert.AreEqual(-1, rightConflictLines.GetUpperBound(0), "Right conflict lines should be zero."); Assert.AreEqual(0, mergedText.Length, "Combined length should equal start length."); }
public void The_result_is_LeftFile_plus_RightFile() { // inputs string fileBodyLeft = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string fileBodyRight = Helper.GetResource(resourcePrefix + "ThreeDiffLines.txt"); string fileExpected = Helper.GetResource(resourcePrefix + "AllLinesDifferent_Expected.txt"); TypeOfDiff typeOfDiff = SlyceMerge.PerformTwoWayDiff(identifyConflictsAndRegions, fileBodyLeft, fileBodyRight, out leftConflictLines, out rightConflictLines, out mergedText); Assert.AreEqual(TypeOfDiff.Conflict, typeOfDiff, "TypeOfDiffs are different."); Assert.AreEqual(fileExpected.Trim(), mergedText.Trim(), "Combined file should equal expected file."); Assert.AreEqual(2, leftConflictLines.GetUpperBound(0), "Should be one left line in conflict."); Assert.AreEqual(2, rightConflictLines.GetUpperBound(0), "Should be one right line in conflict."); Assert.AreEqual(0, leftConflictLines[0].StartLine, "Left conflict lines should start at line 1 (index 0)."); Assert.AreEqual(3, rightConflictLines[0].StartLine, "Right conflict lines should start at line 4 (index 3)."); }
public void The_left_conflict_lines_start_from_0() { // inputs string fileBodyLeft = Helper.GetResource(resourcePrefix + "ThreeLines.txt"); string fileBodyRight = Helper.GetResource(resourcePrefix + "ThreeLines_FirstLineChanged.txt"); string fileExpected = Helper.GetResource(resourcePrefix + "FirstLineDifferent_Expected.txt"); TypeOfDiff typeOfDiff = SlyceMerge.PerformTwoWayDiff(identifyConflictsAndRegions, fileBodyLeft, fileBodyRight, out leftConflictLines, out rightConflictLines, out mergedText); Assert.AreEqual(TypeOfDiff.Conflict, typeOfDiff, "TypeOfDiffs are different."); Assert.AreEqual(fileExpected.Trim(), mergedText.Trim(), "Combined file should equal expected file."); Assert.AreEqual(0, leftConflictLines.GetUpperBound(0), "Should be one left line in conflict."); Assert.AreEqual(0, rightConflictLines.GetUpperBound(0), "Should be one right line in conflict."); Assert.AreEqual(0, leftConflictLines[0].StartLine, "Left conflict lines should start at line 1 (index 0)."); Assert.AreEqual(1, rightConflictLines[0].StartLine, "Right conflict lines should start at line 2 (index 1)."); }
private void ProcessRange(ExtendedRange range) { for (int i = 0; i < range.ChangedRange.Count; i++) { string line = (string)range.ChangedRange[i]; vdo.RightLines.Add(new DiffLine(line, range.ChangeType)); } for (int i = 0; i < range.OriginalRange.Count; i++) { string line = (string)range.OriginalRange[i]; vdo.LeftLines.Add(new DiffLine(line, range.ChangeType)); } for (int i = 0; i < range.OriginalRange.Count - range.ChangedRange.Count; i++) { vdo.RightLines.Add(new DiffLine("", range.ChangeType, true)); } for (int i = 0; i < range.ChangedRange.Count - range.OriginalRange.Count; i++) { vdo.LeftLines.Add(new DiffLine("", range.ChangeType, true)); } switch (range.ChangeType) { case ChangeType.User: vdo.DiffType = SlyceMerge.CombineDiffTypes(vdo.DiffType, TypeOfDiff.UserChangeOnly); break; case ChangeType.Template: vdo.DiffType = SlyceMerge.CombineDiffTypes(vdo.DiffType, TypeOfDiff.TemplateChangeOnly); break; case ChangeType.UserAndTemplate: vdo.DiffType = SlyceMerge.CombineDiffTypes(vdo.DiffType, TypeOfDiff.UserAndTemplateChange); break; default: break; } }
public void The_merged_file_equals_the_start_file() { // inputs string fileBodyLeft = File.ReadAllText(@"..\..\Notes.txt"); string fileBodyRight = fileBodyLeft; TypeOfDiff typeOfDiff = SlyceMerge.PerformTwoWayDiff(identifyConflictsOnly, fileBodyLeft, fileBodyRight, out leftConflictLines, out rightConflictLines, out mergedText); // ignore differences in trailing CrLf fileBodyLeft = fileBodyLeft.Trim(); mergedText = mergedText.Trim(); Assert.AreEqual(TypeOfDiff.ExactCopy, typeOfDiff, "TypeOfDiffs are different."); Assert.AreEqual(-1, leftConflictLines.GetUpperBound(0), "Left conflict lines should be zero."); Assert.AreEqual(-1, rightConflictLines.GetUpperBound(0), "Right conflict lines should be zero."); Assert.AreEqual(fileBodyLeft, mergedText, "Merged text should equal start text."); }
public virtual TypeOfDiff Diff() { TypeOfDiff diff = TypeOfDiff.ExactCopy; DiffTypeExcludingChildren = TypeOfDiff.ExactCopy; if (MergedObj != null) { DiffTypeExcludingChildren = TypeOfDiff.ExactCopy; } else if (baseConstructs.PrevGen == null) { if (baseConstructs.NewGen == null && baseConstructs.User == null) { DiffTypeExcludingChildren = CombineChildDiffTypes(diffTypeExcChildren, TypeOfDiff.Warning); } else if (baseConstructs.NewGen == null) { DiffTypeExcludingChildren = CombineChildDiffTypes(diffTypeExcChildren, TypeOfDiff.UserChangeOnly); } else if (baseConstructs.User == null) { DiffTypeExcludingChildren = CombineChildDiffTypes(diffTypeExcChildren, TypeOfDiff.TemplateChangeOnly); } else if (baseConstructs.User.IsTheSame(baseConstructs.NewGen, ComparisonDepth.Outer)) { DiffTypeExcludingChildren = CombineChildDiffTypes(diffTypeExcChildren, TypeOfDiff.ExactCopy); } else { DiffTypeExcludingChildren = CombineChildDiffTypes(diffTypeExcChildren, TypeOfDiff.Conflict); } if (baseConstructs.NewGen != null && baseConstructs.User != null && baseConstructs.GetFirstNonNullObject().IsLeaf) { // Do a diff on the body text of our BaseConstructs string userText = GetFullText(UserObj).TrimStart(Environment.NewLine.ToCharArray()); string newgenText = GetFullText(NewGenObj).TrimStart(Environment.NewLine.ToCharArray()); TypeOfDiff result = SlyceMerge.PerformTwoWayDiff(userText, newgenText); DiffTypeExcludingChildren = CombineChildDiffTypes(diffTypeExcChildren, result); } } else { if (BaseConstructsAreSame == false) { // Do a diff on the outer text of our BaseConstructs string userText = GetOuterText(UserObj); string newgenText = GetOuterText(NewGenObj); string prevgenText = GetOuterText(PrevGenObj); string mergedText; DiffTypeExcludingChildren = SlyceMerge.Perform3wayDiff(userText, prevgenText, newgenText, out mergedText, false).DiffType; } // Also diff ourselves, looking at more than a basic signature comparison but not looking at children (we have already done that above) if (baseConstructs.PrevGen == null) { if (baseConstructs.NewGen == null) { DiffTypeExcludingChildren = CombineChildDiffTypes(diffTypeExcChildren, TypeOfDiff.UserChangeOnly); } else if (baseConstructs.User == null && ParentTree.UserCodeRoot != null) // if the user file is null it may not have been generated yet - this is the first run of this project. { DiffTypeExcludingChildren = CombineChildDiffTypes(diffTypeExcChildren, TypeOfDiff.TemplateChangeOnly); } else { DiffTypeExcludingChildren = CombineChildDiffTypes(diffTypeExcChildren, TypeOfDiff.UserAndTemplateChange); } } else { if (baseConstructs.PrevGen.IsTheSame(baseConstructs.NewGen, ComparisonDepth.Outer) == false) { // If NewGen is null, this will return false. DiffTypeExcludingChildren = CombineChildDiffTypes(diffTypeExcChildren, TypeOfDiff.TemplateChangeOnly); } if (baseConstructs.PrevGen.IsTheSame(baseConstructs.User, ComparisonDepth.Outer) == false) { // If User is null, this will return false. DiffTypeExcludingChildren = CombineChildDiffTypes(diffTypeExcChildren, TypeOfDiff.UserChangeOnly); } if (baseConstructs.NewGen != null && baseConstructs.User != null && diffTypeExcChildren == TypeOfDiff.Conflict && baseConstructs.NewGen.IsTheSame(baseConstructs.User, ComparisonDepth.Outer)) { DiffTypeExcludingChildren = TypeOfDiff.UserAndTemplateChange; } if (baseConstructs.NewGen == null && baseConstructs.User == null) { DiffTypeExcludingChildren = TypeOfDiff.UserAndTemplateChange; } } if (baseConstructs.GetFirstNonNullObject().IsLeaf) { // Do a diff on the body text of our BaseConstructs string userText = GetBodyText(UserObj).TrimStart(Environment.NewLine.ToCharArray()); string newgenText = GetBodyText(NewGenObj).TrimStart(Environment.NewLine.ToCharArray()); string prevgenText = GetBodyText(PrevGenObj).TrimStart(Environment.NewLine.ToCharArray()); string mergedText; TypeOfDiff result = SlyceMerge.Perform3wayDiff(userText, prevgenText, newgenText, out mergedText).DiffType; DiffTypeExcludingChildren = CombineChildDiffTypes(diffTypeExcChildren, result); } if (baseConstructs.NewGen != null && ParentTree.PrevGenCodeRoot == null && ParentTree.UserCodeRoot == null) { // Template base construct exists, but Prevgen and User CodeRoots haven't been added.. Make it an exact copy. DiffTypeExcludingChildren = TypeOfDiff.ExactCopy; } } // Diff out child nodes. foreach (CodeRootMapNode node in children) { diff = CombineChildDiffTypes(diff, node.Diff()); } diff = CombineChildDiffTypes(diff, diffTypeExcChildren); return(diff); }
/// <summary> /// Returns a IBaseConstruct which is the result of merging the BaseConstructs in this subtree. /// </summary> /// <returns>A IBaseConstruct which is the result of merging the BaseConstructs in this subtree.</returns> /// <exception cref="InvalidOperationException">Thrown if there are no BaseConstructs in this node /// or any of its children.</exception> public virtual IBaseConstruct GetMergedBaseConstruct() { if (mergedObj != null) { return(mergedObj); } IBaseConstruct newBc = baseConstructs.GetFirstNonNullObject(); if (newBc == null) { throw new InvalidOperationException( "Cannot create a merged IBaseConstruct because this node contains no data"); } newBc = newBc.Clone(); if (baseConstructs.DetermineMissingConstructs() == MissingObject.None) { bool result = newBc.CustomMergeStep(baseConstructs.User, baseConstructs.NewGen, baseConstructs.PrevGen); if (result == false) { // Need to notify the user of this issue. throw new MergeException("Could not perform automatic merge, CustomMergeStep failed. ", GetFirstValidBaseConstruct().FullyQualifiedIdentifer, GetFirstValidBaseConstruct().GetType().ToString()); } } if (newBc is IBody) { IBody bodyNode = (IBody)newBc; string userText = GetBodyText(UserObj); string newgenText = GetBodyText(NewGenObj); string prevgenText = GetBodyText(PrevGenObj); if (UserObj == null && NewGenObj != null) { bodyNode.BodyText = newgenText; } else if (NewGenObj == null && UserObj != null) { bodyNode.BodyText = userText; } else { string mergedText; TypeOfDiff result = SlyceMerge.Perform3wayDiff(userText, prevgenText, newgenText, out mergedText).DiffType; if (result == TypeOfDiff.Conflict) { throw new InvalidOperationException("Cannot merge BaseConstructs if there is a conflict in their body text."); } bodyNode.BodyText = mergedText; } } foreach (CodeRootMapNode child in children) { MissingObject missingObjects = child.DetermineMissingConstructs(); if ((missingObjects & MissingObject.NewGen) != 0 && (missingObjects & MissingObject.User) != 0) { continue; } IBaseConstruct childBC = child.GetMergedBaseConstruct(); newBc.AddChild(childBC); } return(newBc); }
/// <summary> /// Performs the diff between the 3 files, even if some of them do not exist. /// </summary> protected override bool PerformDiffInternal() { ////////////////////////// MergedFile = NewGenFile; if (!UserFile.IsFileOnDisk) { CurrentDiffResult.DiffType = TypeOfDiff.NewFile; } else if (UserFile.HexStringMD5() == NewGenFile.HexStringMD5()) { CurrentDiffResult.DiffType = TypeOfDiff.ExactCopy; } else { CurrentDiffResult.DiffType = TypeOfDiff.TemplateChangeOnly; } return(true); /////////////////////////// if (IntelliMerge == IntelliMergeType.Overwrite) { CurrentDiffResult.DiffType = TypeOfDiff.ExactCopy; MergedFile = NewGenFile; return(true); } if (IntelliMerge == IntelliMergeType.CreateOnly) { CurrentDiffResult.DiffType = TypeOfDiff.ExactCopy; MergedFile = UserFile.HasContents ? UserFile : NewGenFile; return(true); } if (UserFile.HasContents == false && PrevGenFile.HasContents == false && NewGenFile.HasContents == false) { throw new InvalidOperationException("Cannot perform a diff if there are no files!"); } if (MergedFileExists) { CurrentDiffResult.DiffPerformedSuccessfully = true; CurrentDiffResult.DiffType = TypeOfDiff.ExactCopy; CurrentDiffResult.DiffWarningDescription = CurrentDiffResult.ParserWarningDescription = ""; return(true); } if (PrevGenFile.HasContents && UserFile.HasContents && NewGenFile.HasContents) { // Perform 3-way diff string fileBodyParent = PrevGenFile.GetContents(); string fileBodyUser = UserFile.GetContents(); // Template code is not formatted until it is needed. Do the formatting here. string fileBodyGenerated; string mergedText; SlyceMergeResult slyceMerge; if (IntelliMerge == IntelliMergeType.CSharp) { if (NewGenFile.GetContents().Trim() == string.Empty) { fileBodyGenerated = ""; } else { CSharpParser formatter = new CSharpParser(); formatter.ParseCode(NewGenFile.FilePath, NewGenFile.GetContents()); if (formatter.ErrorOccurred) { CurrentDiffResult.ParserWarningDescription = formatter.GetFormattedErrors(); return(false); } CodeRoot codeRoot = (CodeRoot)formatter.CreatedCodeRoot; fileBodyGenerated = codeRoot.ToString(); } slyceMerge = SlyceMerge.Perform3wayDiff(fileBodyUser, fileBodyParent, fileBodyGenerated, out mergedText, false); } else { fileBodyGenerated = NewGenFile.GetContents(); slyceMerge = SlyceMerge.Perform3wayDiff(fileBodyUser, fileBodyParent, fileBodyGenerated, out mergedText, true); MergedFile = new TextFile(mergedText); } CurrentDiffResult.DiffType = slyceMerge.DiffType; if (slyceMerge.DiffType == TypeOfDiff.Warning) { // TODO: What should be done here? throw new Exception( "There was a warning during the diff process when there shouldn't have been. Please report this to Slyce."); } if (slyceMerge.DiffType != TypeOfDiff.ExactCopy) { return(PerformSuperDiff()); } // File was exact copy - use user version MergedFile = new TextFile(fileBodyUser); } else if (PrevGenFile.HasContents && UserFile.HasContents == false && NewGenFile.HasContents) { // No user file, just use the template file CurrentDiffResult.DiffType = TypeOfDiff.Warning; CurrentDiffResult.DiffWarningDescription = "The User's version of this file has been deleted or renamed, but the Template and previous version of this file still exist."; MergedFile = new TextFile(NewGenFile.GetContents()); } else if (PrevGenFile.HasContents == false && UserFile.HasContents && NewGenFile.HasContents) { //CurrentDiffResult.DiffType = TypeOfDiff.Warning; //CurrentDiffResult.DiffWarningDescription = // "User version of a file clashes with a new file the template is trying to create."; // Perform 2-way diff string fileBodyNewGen = NewGenFile.GetContents(); string fileBodyUser = UserFile.GetContents(); CurrentDiffResult.DiffType = SlyceMerge.PerformTwoWayDiff(fileBodyNewGen, fileBodyUser); if (CurrentDiffResult.DiffType != TypeOfDiff.ExactCopy) { // Also perform a super diff return(PerformSuperDiff()); } MergedFile = new TextFile(fileBodyUser); } else if (PrevGenFile.HasContents == false && UserFile.HasContents == false && NewGenFile.HasContents) { // The template has added a new file. CurrentDiffResult.DiffType = TypeOfDiff.ExactCopy; MergedFile = new TextFile(NewGenFile.GetContents()); } else { // Cases covered by this else: // * User and prevgen file exist, no template // * Prevgen, no user or template. // * User file, no template or prevgen // TODO: Shouldn't really be a warning... CurrentDiffResult.DiffType = TypeOfDiff.Warning; throw new Exception(string.Format("TODO: determine course of action, what should be copied to staging folder, because no file exists: \nparent file path:\"{0}\" : {1}\nuser file path:\"{2}\" : {3}\ntemplate file path:\"{4}\" : {5}", PrevGenFile.FilePath, PrevGenFile.HasContents, UserFile.FilePath, UserFile.HasContents, NewGenFile.FilePath, NewGenFile.HasContents)); } return(true); }
internal void PerformDiffOfFile(DiffFile diffFile, ref bool fileNeedsToBeCounted) { // Don't process files that had errors during generation for (int errFileCounter = 0; errFileCounter < GenerationErrors.Count; errFileCounter++) { if (Slyce.Common.Utility.StringsAreEqual(diffFile.RelativePath, GenerationErrors[errFileCounter].FileName, false)) { //continue; return; } } if (UniqueFilesForCount[diffFile.RelativePath] != null && (bool)UniqueFilesForCount[diffFile.RelativePath] == false) { fileNeedsToBeCounted = true; UniqueFilesForCount[diffFile.RelativePath] = true; } else { fileNeedsToBeCounted = false; } if (diffFile.Path.IndexOf(".aaz") > 0 || diffFile.HasParseError) { //continue; return; } if (FileBeingProcessed != null) { FileBeingProcessed(diffFile.Path); } // Perform a 3-way diff on the file string parentFile = Path.Combine(PreviousGenerationFolder, diffFile.RelativePath); string userFile = Path.Combine(Controller.Instance.ProjectSettings.ProjectPath, diffFile.RelativePath); string templateFile = Path.Combine(Controller.Instance.GetTempFilePathForComponent(ComponentKey.WorkbenchFileGenerator), diffFile.RelativePath); string mergedFile = Path.Combine(StagingFolder, diffFile.RelativePath + ".merged"); if (CheckFilesForModifications(diffFile.RelativePath) == false) { RaiseDiffFinishedEvent(diffFile.Name, TypeOfDiff.ExactCopy); return; } diffFile.FilePathTemplate = templateFile; diffFile.FilePathUser = userFile; diffFile.FilePathPrevGen = parentFile; if (File.Exists(mergedFile)) { bool mergeComplete = true; // Binary files are never in an unknown state, they are all or nothing. // Text files need to be checked. if (diffFile.IsText) { using (TextReader tr = new StreamReader(mergedFile)) { string line; //int lineCounter = 0; while ((line = tr.ReadLine()) != null && mergeComplete) { int pipeIndex = line.IndexOf("|"); int backColor = int.Parse(line.Substring(0, pipeIndex)); if (backColor != -1 && backColor != 0) { mergeComplete = false; } //lineCounter++; } } } if (mergeComplete) { diffFile.DiffType = TypeOfDiff.Warning; } else { diffFile.DiffType = TypeOfDiff.Conflict; } } else { if (diffFile.IsText) { if (File.Exists(parentFile) && File.Exists(userFile) && File.Exists(templateFile)) { // Perform 3-way diff string fileBodyParent = IOUtility.GetTextFileBody(parentFile); string fileBodyUser = IOUtility.GetTextFileBody(userFile); string fileBodyGenerated = IOUtility.GetTextFileBody(templateFile); string mergedText; slyceMerge = SlyceMerge.Perform3wayDiff(fileBodyUser, fileBodyParent, fileBodyGenerated, out mergedText); diffFile.DiffType = slyceMerge.DiffType; string newFile = ""; if (slyceMerge.DiffType != TypeOfDiff.Conflict) { switch (slyceMerge.DiffType) { case TypeOfDiff.ExactCopy: newFile = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newFile); break; case TypeOfDiff.TemplateChangeOnly: newFile = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(templateFile, newFile); break; case TypeOfDiff.UserAndTemplateChange: newFile = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; if (!Directory.Exists(Path.GetDirectoryName(newFile))) { Directory.CreateDirectory(Path.GetDirectoryName(newFile)); } Slyce.Common.Utility.WriteToFile(newFile, mergedText); break; case TypeOfDiff.UserChangeOnly: newFile = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newFile); break; case TypeOfDiff.Warning: throw new Exception("Oops"); } } } else if (File.Exists(parentFile) && File.Exists(userFile) && !File.Exists(templateFile)) { // No template file, just use the user file diffFile.DiffType = TypeOfDiff.UserChangeOnly; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newPath); } else if (File.Exists(parentFile) && !File.Exists(userFile) && File.Exists(templateFile)) { // No user file, just use the template file diffFile.DiffType = TypeOfDiff.TemplateChangeOnly; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(templateFile, newPath); } else if (!File.Exists(parentFile) && File.Exists(userFile) && File.Exists(templateFile)) { // No parent file, make sure the user merges the template and user files SlyceMerge.LineSpan[] userLines; SlyceMerge.LineSpan[] templateLines; string combinedText; diffFile.DiffType = SlyceMerge.PerformTwoWayDiff(false, IOUtility.GetTextFileBody(userFile), IOUtility.GetTextFileBody(templateFile), out userLines, out templateLines, out combinedText); if (diffFile.DiffType == TypeOfDiff.ExactCopy) { string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(templateFile, newPath); } else { throw new NotImplementedException("This scenario has not been handled yet. Please contact [email protected] with: PerformDiffOfFolder(PrevGen file doesn't exist, and TypeOfDiff = " + diffFile.DiffType + ")"); } //diffFile.DiffType = SlyceMerge.TypeOfDiff.Conflict; // TODO: Work out what should be done in this instance //throw new Exception("TODO: determine course of action, what should be copied to staging folder."); //string newPath = templateFile.Replace(ProjectFolder, StagingFolder) + ".copy"; //Utility.FileCopy(templateFile, newPath); } else if (File.Exists(parentFile) && !File.Exists(userFile) && !File.Exists(templateFile)) { // TODO: It looks like the file was deleted by the user, AND it was removed from the template, so therefore the // user doesn't want this file anymore. Get user to confirm? string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(parentFile, newPath); } else if (!File.Exists(parentFile) && !File.Exists(userFile) && File.Exists(templateFile)) { string newPath = templateFile.Replace(Controller.Instance.GetTempFilePathForComponent(ComponentKey.WorkbenchFileGenerator), StagingFolder) + ".copy"; Slyce.Common.Utility.FileCopy(templateFile, newPath); } else if (!File.Exists(parentFile) && File.Exists(userFile) && !File.Exists(templateFile)) { // TODO: Do we really need to go to the effort of copying etc, because it only exists in the user folder, // so if we take no action it will still exist there - that should be fine ;-) string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newPath); } else { // TODO: Shouldn't really be a warning... diffFile.DiffType = TypeOfDiff.Warning; throw new Exception(string.Format("TODO: determine course of action, what should be copied to staging folder, because no file exists: \n{0}\n{1}\n{2}", parentFile, userFile, templateFile)); } } else // Binary file { string crcParent = File.Exists(parentFile) ? Slyce.Common.Utility.GetCheckSumOfFile(parentFile) : ""; string crcTemplate = File.Exists(templateFile) ? Slyce.Common.Utility.GetCheckSumOfFile(templateFile) : ""; string crcUser = File.Exists(userFile) ? Slyce.Common.Utility.GetCheckSumOfFile(userFile) : ""; diffFile.MD5Parent = crcParent; diffFile.MD5Template = crcTemplate; diffFile.MD5User = crcUser; // TODO: perform CheckSum of binary file if (!string.IsNullOrEmpty(crcParent) && !string.IsNullOrEmpty(crcTemplate) && !string.IsNullOrEmpty(crcUser)) { if (crcParent == crcUser && crcUser == crcTemplate) { diffFile.DiffType = TypeOfDiff.ExactCopy; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newPath); } else if (crcParent == crcUser && crcParent != crcTemplate) { diffFile.DiffType = TypeOfDiff.TemplateChangeOnly; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newPath); } else if (crcParent != crcUser && crcParent == crcTemplate) { diffFile.DiffType = TypeOfDiff.UserChangeOnly; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newPath); } else if (crcParent != crcUser && crcUser == crcTemplate) { diffFile.DiffType = TypeOfDiff.UserAndTemplateChange; } } else if (string.IsNullOrEmpty(crcParent) && !string.IsNullOrEmpty(crcTemplate) && !string.IsNullOrEmpty(crcUser)) { diffFile.DiffType = TypeOfDiff.Conflict; } else if (!string.IsNullOrEmpty(crcParent) && !string.IsNullOrEmpty(crcTemplate) && string.IsNullOrEmpty(crcUser)) { diffFile.DiffType = TypeOfDiff.TemplateChangeOnly; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(templateFile, newPath); } else if (!string.IsNullOrEmpty(crcParent) && string.IsNullOrEmpty(crcTemplate) && !string.IsNullOrEmpty(crcUser)) { diffFile.DiffType = TypeOfDiff.UserChangeOnly; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newPath); } else if (string.IsNullOrEmpty(crcParent) && !string.IsNullOrEmpty(crcTemplate) && string.IsNullOrEmpty(crcUser)) { // This is a new file that has been generated diffFile.DiffType = TypeOfDiff.ExactCopy; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(templateFile, newPath); } else { throw new NotImplementedException("Not coded yet. Seems like only one version of binary file exists. Probably just need to copy as-is."); } } } if (diffFile.DiffType != TypeOfDiff.ExactCopy) { // Only perform the costly SuperDiff if it is not an exact copy //ArchAngel.IntelliMerge.DiffItems.DiffFile diffFile = diffFile; PerformSuperDiff(ref diffFile); } if (fileNeedsToBeCounted) { switch (diffFile.DiffType) { case TypeOfDiff.Conflict: m_numConflicts++; break; case TypeOfDiff.ExactCopy: m_numExactCopy++; break; case TypeOfDiff.TemplateChangeOnly: case TypeOfDiff.UserAndTemplateChange: case TypeOfDiff.UserChangeOnly: case TypeOfDiff.Warning: m_numResolvable++; break; default: throw new NotImplementedException("Not coded yet"); } RaiseDiffFinishedEvent(diffFile.Name, diffFile.DiffType); } Slyce.Common.Utility.DeleteFileBrute(templateFile + ".prevgen.md5"); Slyce.Common.Utility.DeleteFileBrute(templateFile + ".user.md5"); if (diffFile.DiffType == TypeOfDiff.ExactCopy) { // Store the MD5 hashes of the files we just diff'd, so we don't do them again. if (File.Exists(parentFile)) { Slyce.Common.Utility.CreateMD5HashFileForTextFile(parentFile, templateFile + ".prevgen.md5"); } if (File.Exists(userFile)) { Slyce.Common.Utility.CreateMD5HashFileForTextFile(userFile, templateFile + ".user.md5"); } } }
/// <summary> /// Populates two Actipro SyntaxEditors with diff-highlighted text. /// </summary> /// <param name="editor1">Actipro SyntaxEditor</param> /// <param name="editor2">Actipro SyntaxEditor</param> /// <param name="text">Fully combined text.</param> /// <param name="lines1">Lines unique to the left file.</param> /// <param name="lines2">Lines unique to the right file.</param> public static void PopulateSyntaxEditors( ActiproSoftware.SyntaxEditor.SyntaxEditor editor1, ActiproSoftware.SyntaxEditor.SyntaxEditor editor2, string text, SlyceMerge.LineSpan[] lines1, SlyceMerge.LineSpan[] lines2) { editor1.Text = text; editor2.Text = text; for (int i = 0; i < lines1.Length; i++) { for (int lineCounter = lines1[i].StartLine; lineCounter <= lines1[i].EndLine; lineCounter++) { editor1.Document.Lines[lineCounter].BackColor = ColourNewGen; editor2.Document.Lines[lineCounter].BackColor = Color.LightGray; editor2.Document.DeleteText(ActiproSoftware.SyntaxEditor.DocumentModificationType.Delete, editor2.Document.Lines[lineCounter].StartOffset, editor2.Document.Lines[lineCounter].Length); } } for (int i = 0; i < lines2.Length; i++) { for (int lineCounter = lines2[i].StartLine; lineCounter <= lines2[i].EndLine; lineCounter++) { editor2.Document.Lines[lineCounter].BackColor = ColourNewGen; editor1.Document.Lines[lineCounter].BackColor = Color.LightGray; editor1.Document.DeleteText(ActiproSoftware.SyntaxEditor.DocumentModificationType.Delete, editor1.Document.Lines[lineCounter].StartOffset, editor1.Document.Lines[lineCounter].Length); } } // Compact the displays int lineCount1 = 0; int lineCount2 = 0; for (int i = editor1.Document.Lines.Count - 1; i >= -1; i--) { Color lineColor = Color.Empty; if (i >= 0) { lineColor = editor1.Document.Lines[i].BackColor; } if (lineColor == Color.Empty && (lineCount1 + lineCount2) > 0) { // Process counted lines int startIndex = i + 1; int condensedLineCount = Math.Max(lineCount1, lineCount2); int numLinesToRemove = lineCount1 + lineCount2 - condensedLineCount; int lastLine = startIndex + lineCount1 + lineCount2 - 1; //if (numLinesToRemove > 0) //{ // // Walk backward when processing Left // for (int removeIndex = lastLine; removeIndex >= startIndex + condensedLineCount; removeIndex--) // { // editor1.Document.Lines[removeIndex].BackColor = editor1.Document.Lines[removeIndex + 1].BackColor; // editor1.Document.Lines.RemoveAt(removeIndex); // int newPos = lastLine - condensedLineCount - (lastLine - removeIndex); // string gg = editor2.Document.Lines[removeIndex].Text; // editor2.Document.Lines[newPos].Text = editor2.Document.Lines[removeIndex].Text; // editor2.Document.Lines[newPos].BackColor = editor2.Document.Lines[removeIndex].BackColor; // editor2.Document.Lines[removeIndex].BackColor = editor2.Document.Lines[removeIndex + 1].BackColor; // editor2.Document.Lines.RemoveAt(removeIndex); // } //} numLinesToRemove = Math.Min(lineCount1, lineCount2); int linesRemoved1 = 0; int linesRemoved2 = 0; for (int x = startIndex + (lineCount1 + lineCount2); x >= startIndex; x--) { if (linesRemoved1 < numLinesToRemove && editor1.Document.Lines[x].BackColor == Color.LightGray) { editor1.Document.Lines[x].BackColor = editor1.Document.Lines[x + 1].BackColor; editor1.Document.Lines.RemoveAt(x); linesRemoved1++; } if (linesRemoved2 < numLinesToRemove && editor2.Document.Lines[x].BackColor == Color.LightGray) { editor2.Document.Lines[x].BackColor = editor2.Document.Lines[x + 1].BackColor; editor2.Document.Lines.RemoveAt(x); linesRemoved2++; } } if (linesRemoved1 != linesRemoved2) throw new Exception("Non-equal number of lines removed."); //if (lineCount1 > lineCount2) //{ // // Remove trailing gray lines from editor2 // for (int removeIndex = startIndex; removeIndex <= startIndex + numLinesToRemove; removeIndex++) // { // string q111 = editor1.Document.Lines[removeIndex].Text; // string gg = editor2.Document.Lines[removeIndex].Text; // editor2.Document.Lines.RemoveAt(removeIndex); // } //} //else if (lineCount2 > lineCount1) //{ // // Remove trailing gray lines from editor1 // for (int removeIndex = lastLine; removeIndex >= startIndex + condensedLineCount; removeIndex--) // { // string q111 = editor1.Document.Lines[removeIndex].Text; // string gg = editor2.Document.Lines[removeIndex].Text; // editor1.Document.Lines.RemoveAt(removeIndex); // } //} lineCount1 = 0; lineCount2 = 0; continue; } else if (lineColor == ColourNewGen) { lineCount1++; } else if (lineColor == Color.LightGray) { lineCount2++; } } // Line Marker Colours, Strikethroughs string layerKey = "Diff"; string indicatorKey = "Diff"; SpanIndicatorLayer layer = new SpanIndicatorLayer(layerKey, 1000); HighlightingStyle highlightingStyle = new HighlightingStyle("Diff", null, Color.Empty, Color.Empty); highlightingStyle.StrikeOutStyle = HighlightingStyleLineStyle.Solid; highlightingStyle.StrikeOutColor = Color.Red; editor1.Document.SpanIndicatorLayers.Add(layer); int lineNumber1 = 1; int lineNumber2 = 1; for (int i = 0; i < editor1.Document.Lines.Count; i++) { // Set the line marker colours if (editor1.Document.Lines[i].BackColor == Color.LightGray && editor2.Document.Lines[i].BackColor == ColourNewGen) { if (i > 0 && editor2.Document.Lines[i - 1].SelectionMarginMarkColor == changedMarkerColour) { editor2.Document.Lines[i].SelectionMarginMarkColor = changedMarkerColour; editor2.Document.Lines[i].BackColor = Color.LightYellow; } else { editor2.Document.Lines[i].SelectionMarginMarkColor = addedMarkerColour; editor2.Document.Lines[i].BackColor = Color.Honeydew; } editor1.Document.Lines[i].BackColor = Color.WhiteSmoke; editor1.Document.Lines[i].CustomLineNumber = string.Empty; editor2.Document.Lines[i].CustomLineNumber = lineNumber2.ToString(); lineNumber2++; } else if (editor1.Document.Lines[i].BackColor == ColourNewGen && editor2.Document.Lines[i].BackColor == Color.LightGray) { editor2.Document.Lines[i].SelectionMarginMarkColor = deletedMarkerColour; editor1.Document.Lines[i].BackColor = Color.MistyRose; editor2.Document.Lines[i].BackColor = Color.WhiteSmoke; editor1.Document.Lines[i].CustomLineNumber = lineNumber1.ToString(); editor2.Document.Lines[i].CustomLineNumber = string.Empty; lineNumber1++; } else if (editor1.Document.Lines[i].BackColor == ColourNewGen && editor2.Document.Lines[i].BackColor == ColourNewGen) { editor2.Document.Lines[i].SelectionMarginMarkColor = changedMarkerColour; editor1.Document.Lines[i].BackColor = Color.LightYellow; editor2.Document.Lines[i].BackColor = Color.LightYellow; layer.Add(new HighlightingStyleSpanIndicator(indicatorKey, highlightingStyle), editor1.Document.Lines[i].TextRange); editor1.Document.Lines[i].CustomLineNumber = lineNumber1.ToString(); editor2.Document.Lines[i].CustomLineNumber = lineNumber2.ToString(); lineNumber1++; lineNumber2++; } else { editor1.Document.Lines[i].CustomLineNumber = lineNumber1.ToString(); editor2.Document.Lines[i].CustomLineNumber = lineNumber2.ToString(); lineNumber1++; lineNumber2++; } } }
/// <summary> /// Populates a single Actipro SyntaxEditor with diff-highlighted text. /// </summary> /// <param name="editor">Actipro SyntaxEditor</param> /// <param name="text">Fully combined text.</param> /// <param name="newLines">Lines unique to the new file.</param> /// <param name="oldLines">Lines unique to the original file.</param> /// <param name="strikeoutLine2Lines"></param> public static void PopulateSyntaxEditor(ActiproSoftware.SyntaxEditor.SyntaxEditor editor, string text, SlyceMerge.LineSpan[] newLines, SlyceMerge.LineSpan[] oldLines, bool strikeoutLine2Lines) { editor.Text = text; SpanIndicatorLayer layer = null; HighlightingStyle highlightingStyle = null; List<int> linesToNotCount = new List<int>(); if (strikeoutLine2Lines) { layer = new SpanIndicatorLayer("Diff", 1000); highlightingStyle = new HighlightingStyle("Diff", null, Color.Empty, Color.Empty); highlightingStyle.StrikeOutStyle = HighlightingStyleLineStyle.Solid; highlightingStyle.StrikeOutColor = Color.Red; editor.Document.SpanIndicatorLayers.Add(layer); } for (int i = 0; i < oldLines.Length; i++) { if (strikeoutLine2Lines) { for (int lineCounter = oldLines[i].StartLine; lineCounter <= oldLines[i].EndLine; lineCounter++) { editor.Document.Lines[lineCounter].BackColor = Color.MistyRose;// ColourUser; editor.Document.Lines[lineCounter].SelectionMarginMarkColor = deletedMarkerColour;// changedMarkerColour; editor.Document.Lines[lineCounter].CustomLineNumber = String.Empty; layer.Add(new HighlightingStyleSpanIndicator("Diff", highlightingStyle), editor.Document.Lines[lineCounter].TextRange); linesToNotCount.Add(lineCounter); } } else { for (int lineCounter = oldLines[i].StartLine; lineCounter <= oldLines[i].EndLine; lineCounter++) { editor.Document.Lines[lineCounter].BackColor = ColourNewGen; editor.Document.Lines[lineCounter].SelectionMarginMarkColor = addedMarkerColour; } } } for (int i = 0; i < newLines.Length; i++) { for (int lineCounter = newLines[i].StartLine; lineCounter <= newLines[i].EndLine; lineCounter++) { editor.Document.Lines[lineCounter].BackColor = Color.Honeydew;// ColourUser; editor.Document.Lines[lineCounter].SelectionMarginMarkColor = addedMarkerColour;// changedMarkerColour; } } // Fix-up changed vs. new/deleted for (int i = 0; i < editor.Document.Lines.Count; i++) { if (editor.Document.Lines[i].SelectionMarginMarkColor == addedMarkerColour) { int startLine = i; int endLine = -1; bool changeProcessed = false; for (int checkCounter = i + 1; checkCounter < editor.Document.Lines.Count; checkCounter++) { if (changeProcessed) { break; } if (editor.Document.Lines[checkCounter].SelectionMarginMarkColor == addedMarkerColour) { continue; } else if (editor.Document.Lines[checkCounter].SelectionMarginMarkColor == deletedMarkerColour) { // We have found a change for (int deleteCounter = checkCounter + 1; deleteCounter < editor.Document.Lines.Count; deleteCounter++) { if (editor.Document.Lines[deleteCounter].SelectionMarginMarkColor != deletedMarkerColour) { endLine = deleteCounter - 1; // Apply the Change colouring for (int changeCounter = startLine; changeCounter <= endLine; changeCounter++) { editor.Document.Lines[changeCounter].SelectionMarginMarkColor = changedMarkerColour; editor.Document.Lines[changeCounter].BackColor = Color.LightYellow; } changeProcessed = true; // We are back to 'normal' lines - no change found i = checkCounter; break; } else { editor.Document.Lines[deleteCounter].CustomLineNumber = string.Empty; } } } else { // We are back to 'normal' lines - no change found i = checkCounter; break; } } } } int lineNumber = 1; for (int i = 0; i < editor.Document.Lines.Count; i++) { if (linesToNotCount.Contains(i)) { editor.Document.Lines[i].CustomLineNumber = string.Empty; } else { editor.Document.Lines[i].CustomLineNumber = lineNumber.ToString(); lineNumber++; } } }
/// <summary> /// /// </summary> /// <param name="editor"></param> /// <param name="text"></param> /// <param name="lines1"></param> /// <param name="lines2"></param> public static void PopulateSyntaxEditor(ActiproSoftware.SyntaxEditor.SyntaxEditor editor, string text, SlyceMerge.LineSpan[] lines1, SlyceMerge.LineSpan[] lines2) { PopulateSyntaxEditor(editor, text, lines1, lines2, false); }