private async Task <LinkedFileMergeResult> MergeLinkedDocumentGroupAsync( IEnumerable <DocumentId> allLinkedDocuments, IEnumerable <DocumentId> linkedDocumentGroup, LinkedFileDiffMergingSessionInfo sessionInfo, IMergeConflictHandler mergeConflictHandler, CancellationToken cancellationToken) { var groupSessionInfo = new LinkedFileGroupSessionInfo(); // Automatically merge non-conflicting diffs while collecting the conflicting diffs var textDifferencingService = _oldSolution.Workspace.Services.GetService <IDocumentTextDifferencingService>() ?? new DefaultDocumentTextDifferencingService(); var appliedChanges = await textDifferencingService.GetTextChangesAsync(_oldSolution.GetDocument(linkedDocumentGroup.First()), _newSolution.GetDocument(linkedDocumentGroup.First()), cancellationToken).ConfigureAwait(false); var unmergedChanges = new List <UnmergedDocumentChanges>(); foreach (var documentId in linkedDocumentGroup.Skip(1)) { appliedChanges = await AddDocumentMergeChangesAsync( _oldSolution.GetDocument(documentId), _newSolution.GetDocument(documentId), appliedChanges.ToList(), unmergedChanges, groupSessionInfo, textDifferencingService, cancellationToken).ConfigureAwait(false); } var originalDocument = _oldSolution.GetDocument(linkedDocumentGroup.First()); var originalSourceText = await originalDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); // Add comments in source explaining diffs that could not be merged IEnumerable <TextChange> allChanges; IList <TextSpan> mergeConflictResolutionSpan = new List <TextSpan>(); if (unmergedChanges.Any()) { mergeConflictHandler ??= _oldSolution.GetDocument(linkedDocumentGroup.First()).GetLanguageService <ILinkedFileMergeConflictCommentAdditionService>(); var mergeConflictTextEdits = mergeConflictHandler.CreateEdits(originalSourceText, unmergedChanges); allChanges = MergeChangesWithMergeFailComments(appliedChanges, mergeConflictTextEdits, mergeConflictResolutionSpan, groupSessionInfo); } else { allChanges = appliedChanges; } groupSessionInfo.LinkedDocuments = _newSolution.GetDocumentIdsWithFilePath(originalDocument.FilePath).Length; groupSessionInfo.DocumentsWithChanges = linkedDocumentGroup.Count(); sessionInfo.LogLinkedFileResult(groupSessionInfo); return(new LinkedFileMergeResult(allLinkedDocuments, originalSourceText.WithChanges(allChanges), mergeConflictResolutionSpan)); }
internal async Task <Solution> WithMergedLinkedFileChangesAsync( Solution oldSolution, SolutionChanges?solutionChanges = null, IMergeConflictHandler mergeConflictHandler = null, CancellationToken cancellationToken = default(CancellationToken)) { // we only log sessioninfo for actual changes committed to workspace which should exclude ones from preview var session = new LinkedFileDiffMergingSession(oldSolution, this, solutionChanges ?? this.GetChanges(oldSolution), logSessionInfo: solutionChanges != null); return((await session.MergeDiffsAsync(mergeConflictHandler, cancellationToken).ConfigureAwait(false)).MergedSolution); }
private async Task<LinkedFileMergeResult> MergeLinkedDocumentGroupAsync( IEnumerable<DocumentId> allLinkedDocuments, IEnumerable<DocumentId> linkedDocumentGroup, LinkedFileDiffMergingSessionInfo sessionInfo, IMergeConflictHandler mergeConflictHandler, CancellationToken cancellationToken) { var groupSessionInfo = new LinkedFileGroupSessionInfo(); // Automatically merge non-conflicting diffs while collecting the conflicting diffs var textDifferencingService = _oldSolution.Workspace.Services.GetService<IDocumentTextDifferencingService>() ?? new DefaultDocumentTextDifferencingService(); var appliedChanges = await textDifferencingService.GetTextChangesAsync(_oldSolution.GetDocument(linkedDocumentGroup.First()), _newSolution.GetDocument(linkedDocumentGroup.First()), cancellationToken).ConfigureAwait(false); var unmergedChanges = new List<UnmergedDocumentChanges>(); foreach (var documentId in linkedDocumentGroup.Skip(1)) { appliedChanges = await AddDocumentMergeChangesAsync( _oldSolution.GetDocument(documentId), _newSolution.GetDocument(documentId), appliedChanges.ToList(), unmergedChanges, groupSessionInfo, textDifferencingService, cancellationToken).ConfigureAwait(false); } var originalDocument = _oldSolution.GetDocument(linkedDocumentGroup.First()); var originalSourceText = await originalDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); // Add comments in source explaining diffs that could not be merged IEnumerable<TextChange> allChanges; IList<TextSpan> mergeConflictResolutionSpan = new List<TextSpan>(); if (unmergedChanges.Any()) { mergeConflictHandler = mergeConflictHandler ?? _oldSolution.GetDocument(linkedDocumentGroup.First()).GetLanguageService<ILinkedFileMergeConflictCommentAdditionService>(); var mergeConflictTextEdits = mergeConflictHandler.CreateEdits(originalSourceText, unmergedChanges); allChanges = MergeChangesWithMergeFailComments(appliedChanges, mergeConflictTextEdits, mergeConflictResolutionSpan, groupSessionInfo); } else { allChanges = appliedChanges; } groupSessionInfo.LinkedDocuments = _newSolution.GetDocumentIdsWithFilePath(originalDocument.FilePath).Length; groupSessionInfo.DocumentsWithChanges = linkedDocumentGroup.Count(); sessionInfo.LogLinkedFileResult(groupSessionInfo); return new LinkedFileMergeResult(allLinkedDocuments, originalSourceText.WithChanges(allChanges), mergeConflictResolutionSpan); }
internal async Task <LinkedFileMergeSessionResult> MergeDiffsAsync(IMergeConflictHandler mergeConflictHandler, CancellationToken cancellationToken) { LinkedFileDiffMergingSessionInfo sessionInfo = new LinkedFileDiffMergingSessionInfo(); var linkedDocumentGroupsWithChanges = _solutionChanges .GetProjectChanges() .SelectMany(p => p.GetChangedDocuments()) .GroupBy(d => _oldSolution.GetDocument(d).FilePath, StringComparer.OrdinalIgnoreCase); var linkedFileMergeResults = new List <LinkedFileMergeResult>(); var updatedSolution = _newSolution; foreach (var linkedDocumentsWithChanges in linkedDocumentGroupsWithChanges) { var documentInNewSolution = _newSolution.GetDocument(linkedDocumentsWithChanges.First()); // Ensure the first document in the group is the first in the list of var allLinkedDocuments = documentInNewSolution.GetLinkedDocumentIds().Add(documentInNewSolution.Id); if (allLinkedDocuments.Length == 1) { continue; } SourceText mergedText; if (linkedDocumentsWithChanges.Count() > 1) { var mergeGroupResult = await MergeLinkedDocumentGroupAsync(allLinkedDocuments, linkedDocumentsWithChanges, sessionInfo, mergeConflictHandler, cancellationToken).ConfigureAwait(false); linkedFileMergeResults.Add(mergeGroupResult); mergedText = mergeGroupResult.MergedSourceText; } else { mergedText = await _newSolution.GetDocument(linkedDocumentsWithChanges.Single()).GetTextAsync(cancellationToken).ConfigureAwait(false); } foreach (var documentId in allLinkedDocuments) { updatedSolution = updatedSolution.WithDocumentText(documentId, mergedText); } } LogLinkedFileDiffMergingSessionInfo(sessionInfo); return(new LinkedFileMergeSessionResult(updatedSolution, linkedFileMergeResults)); }
internal async Task<LinkedFileMergeSessionResult> MergeDiffsAsync(IMergeConflictHandler mergeConflictHandler, CancellationToken cancellationToken) { LinkedFileDiffMergingSessionInfo sessionInfo = new LinkedFileDiffMergingSessionInfo(); var linkedDocumentGroupsWithChanges = _solutionChanges .GetProjectChanges() .SelectMany(p => p.GetChangedDocuments()) .GroupBy(d => _oldSolution.GetDocument(d).FilePath, StringComparer.OrdinalIgnoreCase); var linkedFileMergeResults = new List<LinkedFileMergeResult>(); var updatedSolution = _newSolution; foreach (var linkedDocumentsWithChanges in linkedDocumentGroupsWithChanges) { var documentInNewSolution = _newSolution.GetDocument(linkedDocumentsWithChanges.First()); // Ensure the first document in the group is the first in the list of var allLinkedDocuments = documentInNewSolution.GetLinkedDocumentIds().Add(documentInNewSolution.Id); if (allLinkedDocuments.Length == 1) { continue; } SourceText mergedText; if (linkedDocumentsWithChanges.Count() > 1) { var mergeGroupResult = await MergeLinkedDocumentGroupAsync(allLinkedDocuments, linkedDocumentsWithChanges, sessionInfo, mergeConflictHandler, cancellationToken).ConfigureAwait(false); linkedFileMergeResults.Add(mergeGroupResult); mergedText = mergeGroupResult.MergedSourceText; } else { mergedText = await _newSolution.GetDocument(linkedDocumentsWithChanges.Single()).GetTextAsync(cancellationToken).ConfigureAwait(false); } foreach (var documentId in allLinkedDocuments) { updatedSolution = updatedSolution.WithDocumentText(documentId, mergedText); } } LogLinkedFileDiffMergingSessionInfo(sessionInfo); return new LinkedFileMergeSessionResult(updatedSolution, linkedFileMergeResults); }
internal async Task<Solution> WithMergedLinkedFileChangesAsync( Solution oldSolution, SolutionChanges? solutionChanges = null, IMergeConflictHandler mergeConflictHandler = null, CancellationToken cancellationToken = default(CancellationToken)) { // we only log sessioninfo for actual changes committed to workspace which should exclude ones from preview var session = new LinkedFileDiffMergingSession(oldSolution, this, solutionChanges ?? this.GetChanges(oldSolution), logSessionInfo: solutionChanges != null); return (await session.MergeDiffsAsync(mergeConflictHandler, cancellationToken).ConfigureAwait(false)).MergedSolution; }