internal static void LogSession(Workspace workspace, LinkedFileDiffMergingSessionInfo sessionInfo) { if (sessionInfo.LinkedFileGroups.Count > 1) { LogNewSessionWithLinkedFiles(); LogNumberOfLinkedFileGroupsProcessed(sessionInfo.LinkedFileGroups.Count); foreach (var groupInfo in sessionInfo.LinkedFileGroups) { LogNumberOfIdenticalDiffs(groupInfo.IdenticalDiffs); LogNumberOfIsolatedDiffs(groupInfo.IsolatedDiffs); LogNumberOfOverlappingDistinctDiffs(groupInfo.OverlappingDistinctDiffs); LogNumberOfOverlappingDistinctDiffsWithSameSpan(groupInfo.OverlappingDistinctDiffsWithSameSpan); LogNumberOfOverlappingDistinctDiffsWithSameSpanAndSubstringRelation(groupInfo.OverlappingDistinctDiffsWithSameSpanAndSubstringRelation); LogNumberOfInsertedMergeConflictComments(groupInfo.InsertedMergeConflictComments); LogNumberOfInsertedMergeConflictCommentsAtAdjustedLocation(groupInfo.InsertedMergeConflictCommentsAtAdjustedLocation); if (groupInfo.InsertedMergeConflictComments > 0 || groupInfo.InsertedMergeConflictCommentsAtAdjustedLocation > 0) { Logger.Log(FunctionId.Workspace_Solution_LinkedFileDiffMergingSession_LinkedFileGroup, SessionLogMessage.Create(groupInfo)); } } } }
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); }
private async Task<LinkedFileMergeResult> MergeLinkedDocumentGroupAsync( IEnumerable<DocumentId> linkedDocumentGroup, LinkedFileDiffMergingSessionInfo sessionInfo, CancellationToken cancellationToken) { var groupSessionInfo = new LinkedFileGroupSessionInfo(); // Automatically merge non-conflicting diffs while collecting the conflicting diffs var appliedChanges = await newSolution.GetDocument(linkedDocumentGroup.First()).GetTextChangesAsync(oldSolution.GetDocument(linkedDocumentGroup.First())).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, cancellationToken).ConfigureAwait(false); } var originalDocument = oldSolution.GetDocument(linkedDocumentGroup.First()); var originalSourceText = await originalDocument.GetTextAsync().ConfigureAwait(false); // Add comments in source explaining diffs that could not be merged IEnumerable<TextChange> allChanges; if (unmergedChanges.Any()) { var mergeConflictCommentAdder = originalDocument.GetLanguageService<ILinkedFileMergeConflictCommentAdditionService>(); var commentChanges = mergeConflictCommentAdder.CreateCommentsForUnmergedChanges(originalSourceText, unmergedChanges); allChanges = MergeChangesWithMergeFailComments(appliedChanges, commentChanges, groupSessionInfo); } else { allChanges = appliedChanges; } groupSessionInfo.LinkedDocuments = newSolution.GetDocumentIdsWithFilePath(originalDocument.FilePath).Length; groupSessionInfo.DocumentsWithChanges = linkedDocumentGroup.Count(); sessionInfo.LogLinkedFileResult(groupSessionInfo); return new LinkedFileMergeResult(originalSourceText.WithChanges(allChanges), hasMergeConflicts: unmergedChanges.Any()); }
internal async Task <LinkedFileMergeSessionResult> MergeDiffsAsync(IMergeConflictHandler mergeConflictHandler, CancellationToken cancellationToken) { var 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)); }
private void LogLinkedFileDiffMergingSessionInfo(LinkedFileDiffMergingSessionInfo sessionInfo) { // don't report telemetry if (!_logSessionInfo) { return; } var sessionId = SessionLogMessage.GetNextId(); Logger.Log(FunctionId.Workspace_Solution_LinkedFileDiffMergingSession, SessionLogMessage.Create(sessionId, sessionInfo)); foreach (var groupInfo in sessionInfo.LinkedFileGroups) { Logger.Log(FunctionId.Workspace_Solution_LinkedFileDiffMergingSession_LinkedFileGroup, SessionLogMessage.Create(sessionId, groupInfo)); } }
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> MergeDiffsAsync(CancellationToken cancellationToken) { LinkedFileDiffMergingSessionInfo sessionInfo = new LinkedFileDiffMergingSessionInfo(); var linkedDocumentGroupsWithChanges = solutionChanges .GetProjectChanges() .SelectMany(p => p.GetChangedDocuments()) .GroupBy(d => oldSolution.GetDocument(d).FilePath, StringComparer.InvariantCultureIgnoreCase); var updatedSolution = newSolution; foreach (var linkedDocumentGroup in linkedDocumentGroupsWithChanges) { var allLinkedDocuments = newSolution.GetDocumentIdsWithFilePath(newSolution.GetDocumentState(linkedDocumentGroup.First()).FilePath); if (allLinkedDocuments.Length == 1) { continue; } SourceText mergedText; if (linkedDocumentGroup.Count() > 1) { mergedText = (await MergeLinkedDocumentGroupAsync(linkedDocumentGroup, sessionInfo, cancellationToken).ConfigureAwait(false)).MergedSourceText; } else { mergedText = await newSolution.GetDocument(linkedDocumentGroup.Single()).GetTextAsync(cancellationToken).ConfigureAwait(false); } foreach (var documentId in allLinkedDocuments) { updatedSolution = updatedSolution.WithDocumentText(documentId, mergedText); } } LogLinkedFileDiffMergingSessionInfo(sessionInfo); return(updatedSolution); }
internal async Task<Solution> MergeDiffsAsync(CancellationToken cancellationToken) { LinkedFileDiffMergingSessionInfo sessionInfo = new LinkedFileDiffMergingSessionInfo(); var linkedDocumentGroupsWithChanges = solutionChanges .GetProjectChanges() .SelectMany(p => p.GetChangedDocuments()) .GroupBy(d => oldSolution.GetDocument(d).FilePath, StringComparer.InvariantCultureIgnoreCase); var updatedSolution = newSolution; foreach (var linkedDocumentGroup in linkedDocumentGroupsWithChanges) { var allLinkedDocuments = newSolution.GetDocumentIdsWithFilePath(newSolution.GetDocumentState(linkedDocumentGroup.First()).FilePath); if (allLinkedDocuments.Length == 1) { continue; } SourceText mergedText; if (linkedDocumentGroup.Count() > 1) { mergedText = (await MergeLinkedDocumentGroupAsync(linkedDocumentGroup, sessionInfo, cancellationToken).ConfigureAwait(false)).MergedSourceText; } else { mergedText = await newSolution.GetDocument(linkedDocumentGroup.Single()).GetTextAsync(cancellationToken).ConfigureAwait(false); } foreach (var documentId in allLinkedDocuments) { updatedSolution = updatedSolution.WithDocumentText(documentId, mergedText); } } LogLinkedFileDiffMergingSessionInfo(sessionInfo); return updatedSolution; }
public static KeyValueLogMessage Create(int sessionId, LinkedFileDiffMergingSessionInfo sessionInfo) { return KeyValueLogMessage.Create(m => { m[SessionId] = sessionId.ToString(); m[HasLinkedFile] = (sessionInfo.LinkedFileGroups.Count > 0).ToString(); }); }
private void LogLinkedFileDiffMergingSessionInfo(LinkedFileDiffMergingSessionInfo sessionInfo) { var sessionId = SessionLogMessasge.GetNextId(); Logger.Log(FunctionId.Workspace_Solution_LinkedFileDiffMergingSession, SessionLogMessasge.Create(sessionId, sessionInfo)); foreach (var groupInfo in sessionInfo.LinkedFileGroups) { Logger.Log(FunctionId.Workspace_Solution_LinkedFileDiffMergingSession_LinkedFileGroup, SessionLogMessasge.Create(sessionId, groupInfo)); } }
private void LogLinkedFileDiffMergingSessionInfo(LinkedFileDiffMergingSessionInfo sessionInfo) { if (!_logSessionInfo) { return; } LinkedFileDiffMergingLogger.LogSession(this._newSolution.Workspace, sessionInfo); }
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 )); }
void ITelemetryService.LogLinkedFileDiffMergingSession(LinkedFileDiffMergingSessionInfo session) { }