/// <summary>
            /// Creates a new instance of the compilation info, retaining any already built
            /// compilation state as the now 'old' state
            /// </summary>
            public CompilationTracker Fork(
                ProjectState newProject,
                CompilationTranslationAction translate = null,
                CancellationToken cancellationToken    = default(CancellationToken),
                bool clone = false)
            {
                var state = this.ReadState();

                ValueSource <Compilation> baseCompilationSource = state.Compilation;
                var baseCompilation = baseCompilationSource.GetValue(cancellationToken);

                if (baseCompilation != null)
                {
                    // We have some pre-calculated state to incrementally update
                    var newInProgressCompilationSource = clone
                        ? new WeakConstantValueSource <Compilation>(baseCompilation.Clone())
                        : baseCompilationSource;

                    var intermediateProjects = state is InProgressState
                        ? ((InProgressState)state).IntermediateProjects
                        : ImmutableArray.Create <ValueTuple <ProjectState, CompilationTranslationAction> >();

                    var newIntermediateProjects = translate == null
                         ? intermediateProjects
                         : intermediateProjects.Add(ValueTuple.Create(this.ProjectState, translate));

                    var newState = State.Create(newInProgressCompilationSource, newIntermediateProjects);

                    return(new CompilationTracker(newProject, newState));
                }

                var declarationOnlyCompilation = state.DeclarationOnlyCompilation;

                if (declarationOnlyCompilation != null)
                {
                    if (translate != null)
                    {
                        var compilationSource = clone
                            ? (ValueSource <Compilation>) new WeakConstantValueSource <Compilation>(declarationOnlyCompilation)
                            : (ValueSource <Compilation>) new ConstantValueSource <Compilation>(declarationOnlyCompilation);

                        var intermediateProjects =
                            ImmutableArray.Create <ValueTuple <ProjectState, CompilationTranslationAction> >(ValueTuple.Create(this.ProjectState, translate));

                        return(new CompilationTracker(newProject, new InProgressState(compilationSource, intermediateProjects)));
                    }

                    return(new CompilationTracker(newProject, new LightDeclarationState(declarationOnlyCompilation)));
                }

                // We have nothing.  Just make a tracker that only points to the new project.  We'll have
                // to rebuild its compilation from scratch if anyone asks for it.
                return(new CompilationTracker(newProject));
            }
 public static void CheckKnownActions(CompilationTranslationAction translate)
 {
     if (translate != null)
     {
         Contract.ThrowIfFalse(translate is ProjectAssemblyNameAction ||
                               translate is ProjectCompilationOptionsAction ||
                               translate is ProjectParseOptionsAction ||
                               translate is AddDocumentAction ||
                               translate is RemoveDocumentAction ||
                               translate is RemoveAllDocumentsAction ||
                               translate is TouchDocumentAction);
     }
 }
 public static void CheckKnownActions(CompilationTranslationAction translate)
 {
     if (translate != null)
     {
         Contract.ThrowIfFalse(translate is ProjectAssemblyNameAction ||
                               translate is ProjectCompilationOptionsAction ||
                               translate is ProjectParseOptionsAction ||
                               translate is AddDocumentAction ||
                               translate is RemoveDocumentAction ||
                               translate is RemoveAllDocumentsAction ||
                               translate is TouchDocumentAction);
     }
 }
            /// <summary>
            /// Creates a new instance of the compilation info, retaining any already built
            /// compilation state as the now 'old' state
            /// </summary>
            public CompilationTracker Fork(
                ProjectState newProject,
                CompilationTranslationAction translate = null,
                CancellationToken cancellationToken = default(CancellationToken),
                bool clone = false)
            {
                var state = this.ReadState();

                ValueSource<Compilation> baseCompilationSource = state.Compilation;
                var baseCompilation = baseCompilationSource.GetValue(cancellationToken);
                if (baseCompilation != null)
                {
                    // We have some pre-calculated state to incrementally update
                    var newInProgressCompilationSource = clone
                        ? new WeakConstantValueSource<Compilation>(baseCompilation.Clone())
                        : baseCompilationSource;

                    var intermediateProjects = state is InProgressState
                        ? ((InProgressState)state).IntermediateProjects
                        : ImmutableList.Create<ValueTuple<ProjectState, CompilationTranslationAction>>();

                    var newIntermediateProjects = translate == null
                         ? intermediateProjects
                         : intermediateProjects.Add(ValueTuple.Create(this.ProjectState, translate));

                    var newState = State.Create(newInProgressCompilationSource, newIntermediateProjects);

                    return new CompilationTracker(newProject, newState);
                }

                var declarationOnlyCompilation = state.DeclarationOnlyCompilation;
                if (declarationOnlyCompilation != null)
                {
                    if (translate != null)
                    {
                        var compilationSource = clone
                            ? (ValueSource<Compilation>)new WeakConstantValueSource<Compilation>(declarationOnlyCompilation)
                            : (ValueSource<Compilation>)new ConstantValueSource<Compilation>(declarationOnlyCompilation);

                        var intermediateProjects =
                            ImmutableList.Create<ValueTuple<ProjectState, CompilationTranslationAction>>(ValueTuple.Create(this.ProjectState, translate));

                        return new CompilationTracker(newProject, new InProgressState(compilationSource, intermediateProjects));
                    }

                    return new CompilationTracker(newProject, new LightDeclarationState(declarationOnlyCompilation));
                }

                // We have nothing.  Just make a tracker that only points to the new project.  We'll have
                // to rebuild its compilation from scratch if anyone asks for it.
                return new CompilationTracker(newProject);
            }
 private static bool IsTouchDocumentActionForDocument(CompilationTranslationAction action, DocumentId id)
 => action is CompilationTranslationAction.TouchDocumentAction touchDocumentAction &&
Beispiel #6
0
        /// <summary>
        /// Creates a new snapshot with an updated project and an action that will produce a new
        /// compilation matching the new project out of an old compilation. All dependent projects
        /// are fixed-up if the change to the new project affects its public metadata, and old
        /// dependent compilations are forgotten.
        /// </summary>
        private SolutionState ForkProject(
            ProjectState newProjectState,
            CompilationTranslationAction translate = null,
            bool withProjectReferenceChange = false,
            ImmutableDictionary<string, ImmutableArray<DocumentId>> newLinkedFilesMap = null,
            bool forkTracker = true)
        {
            var projectId = newProjectState.Id;

            var newStateMap = _projectIdToProjectStateMap.SetItem(projectId, newProjectState);
            var newDependencyGraph = withProjectReferenceChange ? CreateDependencyGraph(_projectIds, newStateMap) : _dependencyGraph;
            var newTrackerMap = CreateCompilationTrackerMap(projectId, newDependencyGraph);

            // If we have a tracker for this project, then fork it as well (along with the
            // translation action and store it in the tracker map.
            CompilationTracker tracker;
            if (newTrackerMap.TryGetValue(projectId, out tracker))
            {
                newTrackerMap = newTrackerMap.Remove(projectId);

                if (forkTracker)
                {
                    newTrackerMap = newTrackerMap.Add(projectId, tracker.Fork(newProjectState, translate));
                }
            }

            var modifiedDocumentOnly = translate is CompilationTranslationAction.TouchDocumentAction;
            var newLatestProjectVersion = modifiedDocumentOnly ? _lazyLatestProjectVersion : new Lazy<VersionStamp>(() => newProjectState.Version);

            return this.Branch(
                idToProjectStateMap: newStateMap,
                projectIdToTrackerMap: newTrackerMap,
                dependencyGraph: newDependencyGraph,
                linkedFilesMap: newLinkedFilesMap ?? _linkedFilesMap,
                lazyLatestProjectVersion: newLatestProjectVersion);
        }
Beispiel #7
0
        /// <summary>
        /// Creates a new snapshot with an updated project and an action that will produce a new
        /// compilation matching the new project out of an old compilation. All dependent projects
        /// are fixed-up if the change to the new project affects its public metadata, and old
        /// dependent compilations are forgotten.
        /// </summary>
        private Solution ForkProject(
            ProjectState newProjectState,
            CompilationTranslationAction translate = null,
            bool withProjectReferenceChange = false,
            bool withDocumentListChange = false)
        {
            // make sure we are getting only known translate actions
            CompilationTranslationAction.CheckKnownActions(translate);

            var projectId = newProjectState.Id;

            var newStateMap = this.projectIdToProjectStateMap.SetItem(projectId, newProjectState);
            var newDependencyGraph = withProjectReferenceChange ? CreateDependencyGraph(this.projectIds, newStateMap) : this.dependencyGraph;
            var newTrackerMap = CreateCompilationTrackerMap(projectId, newDependencyGraph);
            var newLinkedFilesMap = withDocumentListChange 
                ? CreateLinkedFilesMapWithChangedProject(projectIdToProjectStateMap[projectId], newProjectState) 
                : this.linkedFilesMap;

            // If we have a tracker for this project, then fork it as well (along with the
            // translation action and store it in the tracker map.
            CompilationTracker state;
            if (newTrackerMap.TryGetValue(projectId, out state))
            {
                newTrackerMap = newTrackerMap.Remove(projectId).Add(projectId, state.Fork(newProjectState, translate));
            }

            var modifiedDocumentOnly = translate is CompilationTranslationAction.TouchDocumentAction;
            var newLatestProjectVersion = modifiedDocumentOnly ? this.lazyLatestProjectVersion : new Lazy<VersionStamp>(() => newProjectState.Version);

            return this.Branch(
                idToProjectStateMap: newStateMap,
                projectIdToTrackerMap: newTrackerMap,
                dependencyGraph: newDependencyGraph,
                linkedFilesMap: newLinkedFilesMap,
                lazyLatestProjectVersion: newLatestProjectVersion);
        }