public static async Task <ProjectDependencyGraph> GetDependencyGraphAsync(Solution solution, CancellationToken cancellationToken)
        {
            var tracker  = TrackWorkspace(solution.Workspace);
            var oldGraph = await tracker.GetGraphAsync(cancellationToken).ConfigureAwait(false);

            return(ProjectDependencyGraph.From(solution, oldGraph, cancellationToken));
        }
Esempio n. 2
0
        private SolutionState(
            BranchId branchId,
            int workspaceVersion,
            SolutionServices solutionServices,
            SolutionId id,
            string filePath,
            IEnumerable<ProjectId> projectIds,
            ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap,
            ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap,
            ImmutableDictionary<string, ImmutableArray<DocumentId>> linkedFilesMap,
            ProjectDependencyGraph dependencyGraph,
            VersionStamp version,
            Lazy<VersionStamp> lazyLatestProjectVersion)
        {
            _branchId = branchId;
            _workspaceVersion = workspaceVersion;
            _id = id;
            _filePath = filePath;
            _solutionServices = solutionServices;
            _projectIds = projectIds.ToImmutableReadOnlyListOrEmpty();
            _projectIdToProjectStateMap = idToProjectStateMap;
            _projectIdToTrackerMap = projectIdToTrackerMap;
            _linkedFilesMap = linkedFilesMap;
            _dependencyGraph = dependencyGraph;
            _version = version;
            _lazyLatestProjectVersion = lazyLatestProjectVersion;

            CheckInvariants();
        }
Esempio n. 3
0
        private SolutionState(
            BranchId branchId,
            int workspaceVersion,
            SolutionServices solutionServices,
            SolutionInfo solutionInfo,
            IEnumerable<ProjectId> projectIds,
            ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap,
            ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap,
            ImmutableDictionary<string, ImmutableArray<DocumentId>> linkedFilesMap,
            ProjectDependencyGraph dependencyGraph,
            Lazy<VersionStamp> lazyLatestProjectVersion)
        {
            _branchId = branchId;
            _workspaceVersion = workspaceVersion;
            _solutionServices = solutionServices;
            _solutionInfo = solutionInfo;
            _projectIds = projectIds.ToImmutableReadOnlyListOrEmpty();
            _projectIdToProjectStateMap = idToProjectStateMap;
            _projectIdToTrackerMap = projectIdToTrackerMap;
            _linkedFilesMap = linkedFilesMap;
            _dependencyGraph = dependencyGraph;
            _lazyLatestProjectVersion = lazyLatestProjectVersion;

            // when solution state is changed, we re-calcuate its checksum
            _lazyChecksums = new AsyncLazy<SolutionStateChecksums>(ComputeChecksumsAsync, cacheResult: true);

            CheckInvariants();
        }
            private async Task <ProjectDependencyGraph> LoadOrComputeGraphAsync(Solution solution, CancellationToken cancellationToken)
            {
                Contract.ThrowIfFalse(solution.BranchId == solution.Workspace.PrimaryBranchId);

                // TODO: make this async too
                var persistenceService = WorkspaceService.GetService <IPersistentStorageService>(solution.Workspace);

                ProjectDependencyGraph graph;

                using (var storage = persistenceService.GetStorage(solution))
                    using (var stream = await storage.ReadStreamAsync(PersistenceName, cancellationToken).ConfigureAwait(false))
                    {
                        if (stream != null)
                        {
                            using (var reader = new ObjectReader(stream))
                            {
                                graph = ProjectDependencyGraph.From(solution, reader, cancellationToken);
                                if (graph != null)
                                {
                                    return(graph);
                                }
                            }
                        }
                    }

                cancellationToken.ThrowIfCancellationRequested();

                // do it the hard way!
                graph = ProjectDependencyGraph.From(solution, cancellationToken);

                // since we built it, we may as well save it for next time
                await SaveGraphAsync(graph, cancellationToken).ConfigureAwait(false);

                return(graph);
            }
Esempio n. 5
0
        private Solution(
            BranchId branchId,
            int workspaceVersion,
            SolutionServices solutionServices,
            SolutionId id,
            string filePath,
            ImmutableList<ProjectId> projectIds,
            ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap,
            ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap,
            ProjectDependencyGraph dependencyGraph,
            VersionStamp version,
            Lazy<VersionStamp> lazyLatestProjectVersion)
        {
            this.branchId = branchId;
            this.workspaceVersion = workspaceVersion;
            this.id = id;
            this.filePath = filePath;
            this.solutionServices = solutionServices;
            this.projectIds = projectIds;
            this.projectIdToProjectStateMap = idToProjectStateMap;
            this.projectIdToTrackerMap = projectIdToTrackerMap;
            this.dependencyGraph = dependencyGraph;
            this.projectIdToProjectMap = ImmutableHashMap<ProjectId, Project>.Empty;
            this.version = version;
            this.lazyLatestProjectVersion = lazyLatestProjectVersion;

            CheckInvariants();
        }
            private async Task SaveGraphAsync(ProjectDependencyGraph graph, CancellationToken cancellationToken)
            {
                Contract.ThrowIfFalse(graph.Solution.BranchId == graph.Solution.Workspace.PrimaryBranchId);

                using (var stream = SerializableBytes.CreateWritableStream())
                    using (var writer = new ObjectWriter(stream))
                    {
                        graph.WriteTo(writer);
                        stream.Position = 0;

                        var persistenceService = WorkspaceService.GetService <IPersistentStorageService>(graph.Solution.Workspace);
                        using (var storage = persistenceService.GetStorage(graph.Solution))
                        {
                            await storage.WriteStreamAsync(PersistenceName, stream, cancellationToken).ConfigureAwait(false);
                        }
                    }
            }
        /// <summary>
        /// Build solution and call specified action on syntax tree and semantic model of a particular file.
        /// </summary>
        /// <param name="solutionPath"></param>
        /// <param name="solutionExplorer"></param>
        public static void BuildSolution(string solutionPath, Action <SyntaxTree, SemanticModel> solutionExplorer)
        {
            var workspace = CreateMSBuildWorkspace();

            Solution solution = OpenSolution(workspace, solutionPath);

            // Set Parser options
            CSharpParseOptions options = CSharpParseOptions.Default
                                         .WithFeatures(new[] { new KeyValuePair <string, string>("flow-analysis", "") });

            var seenProjects = new ConcurrentDictionary <string, bool>();

            Microsoft.CodeAnalysis.ProjectDependencyGraph projectGraph = solution.GetProjectDependencyGraph();
            foreach (var projectId in projectGraph.GetTopologicallySortedProjects())
            {
                if (!seenProjects.TryAdd(solution.GetProject(projectId).FilePath, true))
                {
                    continue;
                }
                Compilation projectCompilation;
                try
                {
                    var solutionWithOptions = solution.WithProjectParseOptions(projectId, options);

                    // Get project compilation
                    projectCompilation = GetCompilation(solutionWithOptions, projectId);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Exception occured while compiling project {projectId}. {ex.Message}: {ex.StackTrace}");
                    continue;
                }
                switch (projectCompilation)
                {
                case CSharpCompilation cSharpCompilation:

                    foreach (SyntaxTree syntaxTree in projectCompilation.SyntaxTrees)
                    {
                        var semanticModel = projectCompilation.GetSemanticModel(syntaxTree);

                        solutionExplorer(syntaxTree, semanticModel);
                    }
                    break;
                }
            }
        }
Esempio n. 8
0
        private SolutionState Branch(
            IEnumerable<ProjectId> projectIds = null,
            ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap = null,
            ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap = null,
            ImmutableDictionary<string, ImmutableArray<DocumentId>> linkedFilesMap = null,
            ProjectDependencyGraph dependencyGraph = null,
            VersionStamp? version = default(VersionStamp?),
            Lazy<VersionStamp> lazyLatestProjectVersion = null)
        {
            var branchId = GetBranchId();

            projectIds = projectIds ?? _projectIds;
            idToProjectStateMap = idToProjectStateMap ?? _projectIdToProjectStateMap;
            projectIdToTrackerMap = projectIdToTrackerMap ?? _projectIdToTrackerMap;
            linkedFilesMap = linkedFilesMap ?? _linkedFilesMap;
            dependencyGraph = dependencyGraph ?? _dependencyGraph;
            version = version.HasValue ? version.Value : _version;
            lazyLatestProjectVersion = lazyLatestProjectVersion ?? _lazyLatestProjectVersion;

            if (branchId == _branchId &&
                projectIds == _projectIds &&
                idToProjectStateMap == _projectIdToProjectStateMap &&
                projectIdToTrackerMap == _projectIdToTrackerMap &&
                linkedFilesMap == _linkedFilesMap &&
                dependencyGraph == _dependencyGraph &&
                version == _version &&
                lazyLatestProjectVersion == _lazyLatestProjectVersion)
            {
                return this;
            }

            return new SolutionState(
                branchId,
                _workspaceVersion,
                _solutionServices,
                _id,
                _filePath,
                projectIds,
                idToProjectStateMap,
                projectIdToTrackerMap,
                linkedFilesMap,
                dependencyGraph,
                version.Value,
                lazyLatestProjectVersion);
        }
Esempio n. 9
0
        private ImmutableDictionary<ProjectId, CompilationTracker> CreateCompilationTrackerMap(ProjectId projectId, ProjectDependencyGraph dependencyGraph)
        {
            var builder = ImmutableDictionary.CreateBuilder<ProjectId, CompilationTracker>();
            var dependencies = dependencyGraph.GetProjectsThatTransitivelyDependOnThisProject(projectId);

            foreach (var projectIdAndTracker in _projectIdToTrackerMap)
            {
                var id = projectIdAndTracker.Key;
                var tracker = projectIdAndTracker.Value;

                if (!tracker.HasCompilation)
                {
                    continue;
                }

                var canReuse = id == projectId || !dependencies.Contains(id);
                builder.Add(id, canReuse ? tracker : tracker.Fork(tracker.ProjectState));
            }

            return builder.ToImmutable();
        }
Esempio n. 10
0
        /// <summary>
        /// Links the solution project assemblies to the given P# project.
        /// </summary>
        /// <param name="project">Project</param>
        /// <param name="graph">ProjectDependencyGraph</param>
        private void LinkSolutionAssembliesToProject(Project project, ProjectDependencyGraph graph)
        {
            var projectPath = this.OutputDirectoryMap[project.AssemblyName];

            foreach (var projectId in graph.GetProjectsThatThisProjectTransitivelyDependsOn(project.Id))
            {
                var requiredProject = this.CompilationContext.GetSolution().GetProject(projectId);
                var assemblyPath = this.ProjectAssemblyPathMap[requiredProject.AssemblyName];
                var fileName = projectPath + Path.DirectorySeparatorChar + requiredProject.AssemblyName + ".dll";

                this.CopyAssembly(assemblyPath, fileName);
            }
        }
Esempio n. 11
0
        private SolutionState Branch(
            SolutionInfo solutionInfo = null,
            IEnumerable<ProjectId> projectIds = null,
            ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap = null,
            ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap = null,
            ImmutableDictionary<string, ImmutableArray<DocumentId>> linkedFilesMap = null,
            ProjectDependencyGraph dependencyGraph = null,
            Lazy<VersionStamp> lazyLatestProjectVersion = null)
        {
            var branchId = GetBranchId();

            solutionInfo = solutionInfo ?? _solutionInfo;
            projectIds = projectIds ?? _projectIds;
            idToProjectStateMap = idToProjectStateMap ?? _projectIdToProjectStateMap;
            projectIdToTrackerMap = projectIdToTrackerMap ?? _projectIdToTrackerMap;
            linkedFilesMap = linkedFilesMap ?? _linkedFilesMap;
            dependencyGraph = dependencyGraph ?? _dependencyGraph;
            lazyLatestProjectVersion = lazyLatestProjectVersion ?? _lazyLatestProjectVersion;

            if (branchId == _branchId &&
                solutionInfo == _solutionInfo &&
                projectIds == _projectIds &&
                idToProjectStateMap == _projectIdToProjectStateMap &&
                projectIdToTrackerMap == _projectIdToTrackerMap &&
                linkedFilesMap == _linkedFilesMap &&
                dependencyGraph == _dependencyGraph &&
                lazyLatestProjectVersion == _lazyLatestProjectVersion)
            {
                return this;
            }


            return new SolutionState(
                branchId,
                _workspaceVersion,
                _solutionServices,
                solutionInfo,
                projectIds,
                idToProjectStateMap,
                projectIdToTrackerMap,
                linkedFilesMap,
                dependencyGraph,
                lazyLatestProjectVersion);
        }
Esempio n. 12
0
        /// <summary>
        /// Links the external references to the given P# compilation.
        /// </summary>
        /// <param name="project">Project</param>
        /// <param name="graph">ProjectDependencyGraph</param>
        private void LinkExternalAssembliesToProject(Project project, ProjectDependencyGraph graph)
        {
            var projectPath = this.OutputDirectoryMap[project.AssemblyName];

            foreach (var projectId in graph.GetProjectsThatThisProjectTransitivelyDependsOn(project.Id))
            {
                var requiredProject = this.CompilationContext.GetSolution().GetProject(projectId);
                foreach (var reference in requiredProject.MetadataReferences)
                {
                    //if (!(reference is PortableExecutableReference))
                    //{
                    //    continue;
                    //}

                    var fileName = Path.Combine(projectPath, Path.GetFileName(reference.Display));
                    this.CopyAssembly(reference.Display, fileName);
                }
            }
        }
Esempio n. 13
0
        private Solution Branch(
            ImmutableList<ProjectId> projectIds = null,
            ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap = null,
            ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap = null,
            ProjectDependencyGraph dependencyGraph = null,
            VersionStamp? version = default(VersionStamp?),
            Lazy<VersionStamp> lazyLatestProjectVersion = null)
        {
            var branchId = GetBranchId();

            projectIds = projectIds ?? this.projectIds;
            idToProjectStateMap = idToProjectStateMap ?? this.projectIdToProjectStateMap;
            projectIdToTrackerMap = projectIdToTrackerMap ?? this.projectIdToTrackerMap;
            dependencyGraph = dependencyGraph ?? this.dependencyGraph;
            version = version.HasValue ? version.Value : this.version;
            lazyLatestProjectVersion = lazyLatestProjectVersion ?? this.lazyLatestProjectVersion;

            if (branchId == this.branchId &&
                projectIds == this.projectIds &&
                idToProjectStateMap == this.projectIdToProjectStateMap &&
                projectIdToTrackerMap == this.projectIdToTrackerMap &&
                dependencyGraph == this.dependencyGraph &&
                version == this.version &&
                lazyLatestProjectVersion == this.lazyLatestProjectVersion)
            {
                return this;
            }

            return new Solution(
                branchId,
                this.workspaceVersion,
                this.solutionServices,
                this.id,
                this.filePath,
                projectIds,
                idToProjectStateMap,
                projectIdToTrackerMap,
                dependencyGraph,
                version.Value,
                lazyLatestProjectVersion);
        }
 public void RecomputeGraphLazily(Solution solution)
 {
     SetLazyGraph(new AsyncLazy <ProjectDependencyGraph>(c => Task.FromResult(ProjectDependencyGraph.From(solution, c)), cacheResult: true));
 }
Esempio n. 15
0
 public TestAccessor(ProjectDependencyGraph instance)
 {
     _instance = instance;
 }
Esempio n. 16
0
        /// <summary>
        /// Links the solution project assemblies to the given P# project.
        /// </summary>
        /// <param name="project">Project</param>
        /// <param name="graph">ProjectDependencyGraph</param>
        private static void LinkSolutionAssembliesToProject(Project project, ProjectDependencyGraph graph)
        {
            var projectPath = CompilationEngine.OutputDirectoryMap[project.AssemblyName];

            foreach (var projectId in graph.GetProjectsThatThisProjectTransitivelyDependsOn(project.Id))
            {
                var requiredProject = ProgramInfo.Solution.GetProject(projectId);
                var assemblyPath = CompilationEngine.ProjectAssemblyPathMap[requiredProject.AssemblyName];
                var fileName = projectPath + Path.DirectorySeparatorChar + requiredProject.AssemblyName + ".dll";

                File.Delete(fileName);
                File.Copy(assemblyPath, fileName);
            }
        }
Esempio n. 17
0
        internal static ProjectDependencyGraph From(Solution newSolution, ProjectDependencyGraph oldGraph, CancellationToken cancellationToken)
        {
            var oldSolution = oldGraph.Solution;

            if (oldSolution == newSolution)
            {
                return(oldGraph);
            }

            // in case old and new are incompatible just build it the hard way
            if (oldSolution.Id != newSolution.Id)
            {
                return(From(newSolution, cancellationToken));
            }

            var map         = oldGraph.projectToProjectsItReferencesMap;
            var reverseMap  = oldGraph.projectToProjectsThatReferenceItMap;
            var differences = newSolution.GetChanges(oldSolution);

            // remove projects that no longer occur in new solution
            foreach (var project in differences.GetRemovedProjects())
            {
                cancellationToken.ThrowIfCancellationRequested();
                ImmutableHashSet <ProjectId> referencedProjectIds;
                if (oldGraph.projectToProjectsItReferencesMap.TryGetValue(project.Id, out referencedProjectIds))
                {
                    map        = map.Remove(project.Id);
                    reverseMap = reverseMap.RemoveAll(referencedProjectIds, project.Id);
                }
            }

            // add projects that don't occur in old solution
            foreach (var project in differences.GetAddedProjects())
            {
                cancellationToken.ThrowIfCancellationRequested();
                var referencedProjectIds = project.ProjectReferences.Select(p => p.ProjectId);
                map        = map.Add(project.Id, ImmutableHashSet.CreateRange <ProjectId>(referencedProjectIds));
                reverseMap = reverseMap.AddAll(referencedProjectIds, project.Id);
            }

            // update projects that are changed.
            foreach (var projectChanges in differences.GetProjectChanges().Where(pc => pc.OldProject.AllProjectReferences != pc.NewProject.AllProjectReferences))
            {
                var projectId = projectChanges.ProjectId;

                cancellationToken.ThrowIfCancellationRequested();
                ImmutableHashSet <ProjectId> oldReferencedProjectIds;
                if (oldGraph.projectToProjectsItReferencesMap.TryGetValue(projectId, out oldReferencedProjectIds))
                {
                    map        = map.Remove(projectId);
                    reverseMap = reverseMap.RemoveAll(oldReferencedProjectIds, projectId);
                }

                var newReferencedProjectIds = newSolution.GetProject(projectId).ProjectReferences.Select(p => p.ProjectId);
                map        = map.Add(projectId, ImmutableHashSet.CreateRange <ProjectId>(newReferencedProjectIds));
                reverseMap = reverseMap.AddAll(newReferencedProjectIds, projectId);
            }

            var version = newSolution.GetLatestProjectVersion();

            return(new ProjectDependencyGraph(newSolution, version, map, reverseMap));
        }