public SolutionChangeSummary(Solution oldSolution, Solution newSolution, SolutionChanges changes)
        {
            OldSolution = oldSolution;
            NewSolution = newSolution;

            foreach (var p in changes.GetProjectChanges())
            {
                TotalProjectsAffected += 1;

                TotalFilesAffected += p.GetAddedDocuments().Count() +
                                      p.GetChangedDocuments().Count() +
                                      p.GetRemovedDocuments().Count() +
                                      p.GetAddedAdditionalDocuments().Count() +
                                      p.GetChangedAdditionalDocuments().Count() +
                                      p.GetRemovedAdditionalDocuments().Count();

                if (p.GetAddedDocuments().Any() || p.GetRemovedDocuments().Any() ||
                    p.GetAddedAdditionalDocuments().Any() || p.GetRemovedAdditionalDocuments().Any() ||
                    p.GetAddedMetadataReferences().Any() || p.GetRemovedMetadataReferences().Any() ||
                    p.GetAddedProjectReferences().Any() || p.GetRemovedProjectReferences().Any() ||
                    p.GetAddedAnalyzerReferences().Any() || p.GetRemovedAnalyzerReferences().Any())
                {
                    TotalFilesAffected += 1;  // The project file itself was affected too.
                }
            }

            var totalProjectsAddedOrRemoved = changes.GetAddedProjects().Count() + changes.GetRemovedProjects().Count();

            TotalFilesAffected    += totalProjectsAddedOrRemoved;
            TotalProjectsAffected += totalProjectsAddedOrRemoved;
        }
        public SolutionChangeSummary(Solution oldSolution, Solution newSolution, SolutionChanges changes)
        {
            OldSolution = oldSolution;
            NewSolution = newSolution;

            foreach (var p in changes.GetProjectChanges())
            {
                TotalProjectsAffected += 1;

                TotalFilesAffected += p.GetAddedDocuments().Count() +
                                      p.GetChangedDocuments().Count() +
                                      p.GetRemovedDocuments().Count() +
                                      p.GetAddedAdditionalDocuments().Count() +
                                      p.GetChangedAdditionalDocuments().Count() +
                                      p.GetRemovedAdditionalDocuments().Count();

                if (p.GetAddedDocuments().Any() || p.GetRemovedDocuments().Any() ||
                    p.GetAddedAdditionalDocuments().Any() || p.GetRemovedAdditionalDocuments().Any() ||
                    p.GetAddedMetadataReferences().Any() || p.GetRemovedMetadataReferences().Any() ||
                    p.GetAddedProjectReferences().Any() || p.GetRemovedProjectReferences().Any() ||
                    p.GetAddedAnalyzerReferences().Any() || p.GetRemovedAnalyzerReferences().Any())
                {
                    TotalFilesAffected += 1;  // The project file itself was affected too.
                }
            }

            var totalProjectsAddedOrRemoved = changes.GetAddedProjects().Count() + changes.GetRemovedProjects().Count();

            TotalFilesAffected += totalProjectsAddedOrRemoved;
            TotalProjectsAffected += totalProjectsAddedOrRemoved;
        }
        public static List <DocumentId> GetDocumentIdsToOpen(this Solution newSolution, Solution oldSolution)
        {
            List <DocumentId> result;

            try
            {
                SolutionChanges          changes = newSolution.GetChanges(oldSolution);
                IEnumerable <DocumentId> first   = changes.GetProjectChanges().SelectMany((ProjectChanges p) => p.GetAddedDocuments());
                IEnumerable <DocumentId> second  = changes.GetProjectChanges().SelectMany((ProjectChanges p) => p.GetChangedDocuments());
                result = first.Concat(second).ToList <DocumentId>();
            }
            catch (Exception)
            {
                result = new List <DocumentId>();
            }
            return(result);
        }
        public virtual async Task <Solution> TryMergeFixesAsync(Solution oldSolution, IEnumerable <CodeAction> codeActions, CancellationToken cancellationToken)
        {
            var changedDocumentsMap = new Dictionary <DocumentId, Document>();
            Dictionary <DocumentId, List <Document> > documentsToMergeMap = null;

            foreach (var codeAction in codeActions)
            {
                // TODO: Parallelize GetChangedSolutionInternalAsync for codeActions
                var changedSolution = await codeAction.GetChangedSolutionInternalAsync(cancellationToken).ConfigureAwait(false);

                var solutionChanges = new SolutionChanges(changedSolution, oldSolution);

                // TODO: Handle added/removed documents
                // TODO: Handle changed/added/removed additional documents

                var documentIdsWithChanges = solutionChanges
                                             .GetProjectChanges()
                                             .SelectMany(p => p.GetChangedDocuments());

                foreach (var documentId in documentIdsWithChanges)
                {
                    var document = changedSolution.GetDocument(documentId);

                    Document existingDocument;
                    if (changedDocumentsMap.TryGetValue(documentId, out existingDocument))
                    {
                        if (existingDocument != null)
                        {
                            changedDocumentsMap[documentId] = null;
                            var documentsToMerge = new List <Document>();
                            documentsToMerge.Add(existingDocument);
                            documentsToMerge.Add(document);
                            documentsToMergeMap             = documentsToMergeMap ?? new Dictionary <DocumentId, List <Document> >();
                            documentsToMergeMap[documentId] = documentsToMerge;
                        }
                        else
                        {
                            documentsToMergeMap[documentId].Add(document);
                        }
                    }
                    else
                    {
                        changedDocumentsMap[documentId] = document;
                    }
                }
            }

            var currentSolution = oldSolution;

            foreach (var kvp in changedDocumentsMap)
            {
                var document = kvp.Value;
                if (document != null)
                {
                    var documentText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    currentSolution = currentSolution.WithDocumentText(kvp.Key, documentText);
                }
            }

            if (documentsToMergeMap != null)
            {
                var mergedDocuments = new ConcurrentDictionary <DocumentId, SourceText>();

                var  documentsToMergeArray = documentsToMergeMap.ToImmutableArray();
                bool mergeFailed           = false;

                var mergeTasks = new Task[documentsToMergeArray.Length];
                for (int i = 0; i < documentsToMergeArray.Length; i++)
                {
                    var kvp              = documentsToMergeArray[i];
                    var documentId       = kvp.Key;
                    var documentsToMerge = kvp.Value;
                    var oldDocument      = oldSolution.GetDocument(documentId);

                    mergeTasks[i] = Task.Run(async() =>
                    {
                        var appliedChanges = (await documentsToMerge[0].GetTextChangesAsync(oldDocument, cancellationToken).ConfigureAwait(false)).ToList();

                        foreach (var document in documentsToMerge.Skip(1))
                        {
                            appliedChanges = await TryAddDocumentMergeChangesAsync(
                                oldDocument,
                                document,
                                appliedChanges,
                                cancellationToken).ConfigureAwait(false);

                            if (appliedChanges == null)
                            {
                                mergeFailed = true;
                                break;
                            }
                        }

                        if (!mergeFailed)
                        {
                            var oldText = await oldDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);
                            var newText = oldText.WithChanges(appliedChanges);
                            mergedDocuments.TryAdd(documentId, newText);
                        }
                    });
                }

                await Task.WhenAll(mergeTasks).ConfigureAwait(false);

                if (mergeFailed)
                {
                    return(null);
                }

                foreach (var kvp in mergedDocuments)
                {
                    currentSolution = currentSolution.WithDocumentText(kvp.Key, kvp.Value);
                }
            }

            return(currentSolution);
        }
        public virtual async Task<Solution> TryMergeFixesAsync(Solution oldSolution, IEnumerable<CodeAction> codeActions, CancellationToken cancellationToken)
        {
            var changedDocumentsMap = new Dictionary<DocumentId, Document>();
            Dictionary<DocumentId, List<Document>> documentsToMergeMap = null;

            foreach (var codeAction in codeActions)
            {
                cancellationToken.ThrowIfCancellationRequested();
                // TODO: Parallelize GetChangedSolutionInternalAsync for codeActions
                var changedSolution = await codeAction.GetChangedSolutionInternalAsync(cancellationToken: cancellationToken).ConfigureAwait(false);

                var solutionChanges = new SolutionChanges(changedSolution, oldSolution);

                // TODO: Handle added/removed documents
                // TODO: Handle changed/added/removed additional documents

                var documentIdsWithChanges = solutionChanges
                    .GetProjectChanges()
                    .SelectMany(p => p.GetChangedDocuments());

                foreach (var documentId in documentIdsWithChanges)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var document = changedSolution.GetDocument(documentId);

                    Document existingDocument;
                    if (changedDocumentsMap.TryGetValue(documentId, out existingDocument))
                    {
                        if (existingDocument != null)
                        {
                            changedDocumentsMap[documentId] = null;
                            var documentsToMerge = new List<Document>();
                            documentsToMerge.Add(existingDocument);
                            documentsToMerge.Add(document);
                            documentsToMergeMap = documentsToMergeMap ?? new Dictionary<DocumentId, List<Document>>();
                            documentsToMergeMap[documentId] = documentsToMerge;
                        }
                        else
                        {
                            documentsToMergeMap[documentId].Add(document);
                        }
                    }
                    else
                    {
                        changedDocumentsMap[documentId] = document;
                    }
                }
            }

            var currentSolution = oldSolution;
            foreach (var kvp in changedDocumentsMap)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var document = kvp.Value;
                if (document != null)
                {
                    var documentText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
                    currentSolution = currentSolution.WithDocumentText(kvp.Key, documentText);
                }
            }

            if (documentsToMergeMap != null)
            {
                var mergedDocuments = new ConcurrentDictionary<DocumentId, SourceText>();
                var documentsToMergeArray = documentsToMergeMap.ToImmutableArray();
                var mergeTasks = new Task[documentsToMergeArray.Length];
                for (int i = 0; i < documentsToMergeArray.Length; i++)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var kvp = documentsToMergeArray[i];
                    var documentId = kvp.Key;
                    var documentsToMerge = kvp.Value;
                    var oldDocument = oldSolution.GetDocument(documentId);

                    mergeTasks[i] = Task.Run(async () =>
                    {
                        var appliedChanges = (await documentsToMerge[0].GetTextChangesAsync(oldDocument, cancellationToken).ConfigureAwait(false)).ToList();

                        foreach (var document in documentsToMerge.Skip(1))
                        {
                            cancellationToken.ThrowIfCancellationRequested();
                            appliedChanges = await TryAddDocumentMergeChangesAsync(
                                oldDocument,
                                document,
                                appliedChanges,
                                cancellationToken).ConfigureAwait(false);
                        }

                        var oldText = await oldDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);
                        var newText = oldText.WithChanges(appliedChanges);
                        mergedDocuments.TryAdd(documentId, newText);
                    });
                }

                await Task.WhenAll(mergeTasks).ConfigureAwait(false);

                foreach (var kvp in mergedDocuments)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    currentSolution = currentSolution.WithDocumentText(kvp.Key, kvp.Value);
                }
            }

            return currentSolution;
        }
Exemple #6
0
 public static bool Any(this SolutionChanges solutionChanges)
 => solutionChanges.GetProjectChanges().Any(x => x.GetChangedDocuments().Any());