private static ImmutableDictionary <DocumentId, SyntaxTree> AddOrUpdateNewTreeToOldMap(
                    Project newProject, Compilation newCompilation, CompilationSet oldSet, CancellationToken cancellationToken)
                {
                    if (!oldSet.Compilation.TryGetValue(out var oldCompilation))
                    {
                        return(ImmutableDictionary.CreateRange(GetNewTreeMap(newProject, newCompilation)));
                    }

                    var map = oldSet.Trees;

                    foreach (var newTree in newCompilation.SyntaxTrees)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        if (oldCompilation.ContainsSyntaxTree(newTree))
                        {
                            continue;
                        }

                        var documentId = newProject.GetDocumentId(newTree);

                        // GetDocumentId will return null for #load'ed trees.
                        // TODO:  Remove this check and add logic to fetch the #load'ed tree's
                        // Document once https://github.com/dotnet/roslyn/issues/5260 is fixed.
                        if (documentId == null)
                        {
                            Debug.Assert(newProject.Solution.Workspace.Kind == WorkspaceKind.Interactive || newProject.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles);
                            continue;
                        }

                        map = map.SetItem(documentId, newTree);
                    }

                    return(map);
                }
                private static ImmutableDictionary <DocumentId, SyntaxTree> AddOrUpdateNewTreeToOldMap(
                    Project newProject, Compilation newCompilation, CompilationSet oldSet, CancellationToken cancellationToken)
                {
                    Compilation oldCompilation;

                    if (!oldSet.Compilation.TryGetValue(out oldCompilation))
                    {
                        return(ImmutableDictionary.CreateRange(GetNewTreeMap(newProject, newCompilation)));
                    }

                    var map = oldSet.Trees;

                    foreach (var newTree in newCompilation.SyntaxTrees)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        if (oldCompilation.ContainsSyntaxTree(newTree))
                        {
                            continue;
                        }

                        var documentId = newProject.GetDocumentId(newTree);
                        Contract.Requires(documentId != null);

                        map = map.SetItem(documentId, newTree);
                    }

                    return(map);
                }
예제 #3
0
            private async Task UpdateVersionCacheAsync(Project project, VersionStamp version, CompilationSet primarySet, CancellationToken cancellationToken)
            {
                var versionMap = GetVersionMapFromBranch(project.Solution.Workspace, project.Solution.BranchId);

                if (!AlreadyHasLatestCompilationSet(versionMap, project.Id, version, out var compilationSet) ||
                    !compilationSet.Compilation.TryGetValue(out var compilation))
                {
                    var newSet = await CompilationSet.CreateAsync(project, compilationSet ?? primarySet, cancellationToken).ConfigureAwait(false);

                    using (_gate.DisposableWrite())
                    {
                        // we still don't have it or if someone has beaten us, check what we have is newer
                        if (!versionMap.TryGetValue(project.Id, out compilationSet) || version != compilationSet.Version)
                        {
                            versionMap[project.Id] = newSet;
                        }
                    }
                }
            }
                private static ImmutableDictionary <DocumentId, SyntaxTree> GetTreeMap(Project project, Compilation compilation, CompilationSet oldCompilationSet, CancellationToken cancellationToken)
                {
                    // enumerable count should take a quick path since ImmutableArray implements ICollection
                    var newTreeCount = compilation.SyntaxTrees.Count();

                    // TODO: all this could go away if this is maintained by project itself and one can just get the map from it.
                    if (oldCompilationSet == null || Math.Abs(oldCompilationSet.Trees.Count - newTreeCount) > RebuildThreshold)
                    {
                        return(ImmutableDictionary.CreateRange(GetNewTreeMap(project, compilation)));
                    }

                    var map = AddOrUpdateNewTreeToOldMap(project, compilation, oldCompilationSet, cancellationToken);

                    // check simple case. most of typing case should hit this.
                    // number of items in the map is same as number of new trees and old compilation doesn't have
                    // more trees than current one
                    if (map.Count == newTreeCount && oldCompilationSet.Trees.Count <= newTreeCount)
                    {
                        return(map);
                    }

                    // a bit more expensive case where there is a document in oldCompilationSet that doesn't exist in new compilation
                    return(RemoveOldTreeFromMap(compilation, oldCompilationSet.Trees, map, cancellationToken));
                }
                public static async Task <CompilationSet> CreateAsync(Project project, CompilationSet oldCompilationSet, CancellationToken cancellationToken)
                {
                    var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                    var version = await project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);

                    var map = GetTreeMap(project, compilation, oldCompilationSet, cancellationToken);

                    ValidateTreeMap(map, project, compilation);
                    return(new CompilationSet(version, GetCompilation(project, compilation), map));
                }
 private bool AlreadyHasLatestCompilationSet(
     Dictionary <ProjectId, CompilationSet> versionMap, ProjectId projectId, VersionStamp version, out CompilationSet compilationSet)
 {
     using (gate.DisposableRead())
     {
         // we still don't have it or if someone has beaten us, check what we have is newer
         return(versionMap.TryGetValue(projectId, out compilationSet) && version == compilationSet.Version);
     }
 }
                private static ImmutableDictionary<DocumentId, SyntaxTree> AddOrUpdateNewTreeToOldMap(
                    Project newProject, Compilation newCompilation, CompilationSet oldSet, CancellationToken cancellationToken)
                {
                    Compilation oldCompilation;
                    if (!oldSet.Compilation.TryGetValue(out oldCompilation))
                    {
                        return ImmutableDictionary.CreateRange(GetNewTreeMap(newProject, newCompilation));
                    }

                    var map = oldSet.Trees;
                    foreach (var newTree in newCompilation.SyntaxTrees)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        if (oldCompilation.ContainsSyntaxTree(newTree))
                        {
                            continue;
                        }

                        var documentId = newProject.GetDocumentId(newTree);
                        Contract.Requires(documentId != null);

                        map = map.SetItem(documentId, newTree);
                    }

                    return map;
                }
                private static ImmutableDictionary<DocumentId, SyntaxTree> GetTreeMap(Project project, Compilation compilation, CompilationSet oldCompilationSet, CancellationToken cancellationToken)
                {
                    // enumerable count should take a quick path since ImmutableArray implements ICollection
                    var newTreeCount = compilation.SyntaxTrees.Count();

                    // TODO: all this could go away if this is maintained by project itself and one can just get the map from it.
                    if (oldCompilationSet == null || Math.Abs(oldCompilationSet.Trees.Count - newTreeCount) > RebuildThreshold)
                    {
                        return ImmutableDictionary.CreateRange(GetNewTreeMap(project, compilation));
                    }

                    var map = AddOrUpdateNewTreeToOldMap(project, compilation, oldCompilationSet, cancellationToken);

                    // check simple case. most of typing case should hit this.
                    // number of items in the map is same as number of new trees and old compilation doesn't have
                    // more trees than current one
                    if (map.Count == newTreeCount && oldCompilationSet.Trees.Count <= newTreeCount)
                    {
                        return map;
                    }

                    // a bit more expensive case where there is a document in oldCompilationSet that doesn't exist in new compilation
                    return RemoveOldTreeFromMap(compilation, oldCompilationSet.Trees, map, cancellationToken);
                }
                public static async Task<CompilationSet> CreateAsync(Project project, CompilationSet oldCompilationSet, CancellationToken cancellationToken)
                {
                    var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
                    var version = await project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);
                    var map = GetTreeMap(project, compilation, oldCompilationSet, cancellationToken);

                    ValidateTreeMap(map, project, compilation);
                    return new CompilationSet(version, GetCompilation(project, compilation), map);
                }
 private bool AlreadyHasLatestCompilationSet(
     Dictionary<ProjectId, CompilationSet> versionMap, ProjectId projectId, VersionStamp version, out CompilationSet compilationSet)
 {
     using (gate.DisposableRead())
     {
         // we still don't have it or if someone has beaten us, check what we have is newer
         return versionMap.TryGetValue(projectId, out compilationSet) && version == compilationSet.Version;
     }
 }
            private async Task UpdateVersionCacheAsync(Project project, VersionStamp version, CompilationSet primarySet, CancellationToken cancellationToken)
            {
                var versionMap = GetVersionMapFromBranch(project.Solution.Workspace, project.Solution.BranchId);

                CompilationSet compilationSet;
                Compilation compilation;
                if (!AlreadyHasLatestCompilationSet(versionMap, project.Id, version, out compilationSet) ||
                    !compilationSet.Compilation.TryGetValue(out compilation))
                {
                    var newSet = await CompilationSet.CreateAsync(project, compilationSet ?? primarySet, cancellationToken).ConfigureAwait(false);

                    using (gate.DisposableWrite())
                    {
                        // we still don't have it or if someone has beaten us, check what we have is newer
                        if (!versionMap.TryGetValue(project.Id, out compilationSet) || version != compilationSet.Version)
                        {
                            versionMap[project.Id] = newSet;
                        }
                    }
                }
            }
                private static ImmutableDictionary<DocumentId, SyntaxTree> AddOrUpdateNewTreeToOldMap(
                    Project newProject, Compilation newCompilation, CompilationSet oldSet, CancellationToken cancellationToken)
                {
                    if (!oldSet.Compilation.TryGetValue(out var oldCompilation))
                    {
                        return ImmutableDictionary.CreateRange(GetNewTreeMap(newProject, newCompilation));
                    }

                    var map = oldSet.Trees;
                    foreach (var newTree in newCompilation.SyntaxTrees)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        if (oldCompilation.ContainsSyntaxTree(newTree))
                        {
                            continue;
                        }

                        var documentId = newProject.GetDocumentId(newTree);

                        // GetDocumentId will return null for #load'ed trees.
                        // TODO:  Remove this check and add logic to fetch the #load'ed tree's
                        // Document once https://github.com/dotnet/roslyn/issues/5260 is fixed.
                        if (documentId == null)
                        {
                            Debug.Assert(newProject.Solution.Workspace.Kind == "Interactive");
                            continue;
                        }

                        map = map.SetItem(documentId, newTree);
                    }

                    return map;
                }