internal void UpdateContextHierarchyIfContainsDocument(IVsHierarchy sharedHierarchy, DocumentId documentId)
        {
            // TODO: This is a very roundabout way to update the context

            // The sharedHierarchy passed in has a new context, but we don't know what it is.
            // The documentId passed in is associated with this sharedHierarchy, and this method
            // will be called once for each such documentId. During this process, one of these
            // documentIds will actually belong to the new SharedItemContextHierarchy. Once we
            // find that one, we can map back to the open buffer and set its active context to
            // the appropriate project.

            var contextHierarchy = LinkedFileUtilities.GetSharedItemContextHierarchy(sharedHierarchy);

            // TODO: linear search
            var matchingProject = CurrentSolution.Projects.FirstOrDefault(p => GetHostProject(p.Id).Hierarchy == contextHierarchy);

            if (matchingProject == null)
            {
                // How?
                return;
            }

            if (!matchingProject.ContainsDocument(documentId))
            {
                // While this documentId is associated with one of the head projects for this
                // sharedHierarchy, it is not associated with the new context hierarchy. Another
                // documentId will be passed to this method and update the context.
                return;
            }

            // This documentId belongs to the new SharedItemContextHierarchy. Update the associated
            // buffer.
            OnDocumentContextUpdated(documentId);
        }
Example #2
0
        public VisualStudioProjectTracker(IThreadingContext threadingContext, IServiceProvider serviceProvider, Workspace workspace, LinkedFileUtilities linkedFileUtilities)
            : base(threadingContext, assertIsForeground: true)
        {
            _projectMap         = new Dictionary <ProjectId, AbstractProject>();
            _projectPathToIdMap = new Dictionary <string, ProjectId>(StringComparer.OrdinalIgnoreCase);

            _serviceProvider     = serviceProvider;
            _workspace           = workspace;
            WorkspaceServices    = workspace.Services;
            _linkedFileUtilities = linkedFileUtilities;

            _vsSolution           = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution));
            _runningDocumentTable = (IVsRunningDocumentTable4)serviceProvider.GetService(typeof(SVsRunningDocumentTable));

            // It's possible that we're loading after the solution has already fully loaded, so see if we missed the event
            var shellMonitorSelection = (IVsMonitorSelection)serviceProvider.GetService(typeof(SVsShellMonitorSelection));

            if (ErrorHandler.Succeeded(shellMonitorSelection.GetCmdUIContextCookie(VSConstants.UICONTEXT.SolutionExistsAndFullyLoaded_guid, out var fullyLoadedContextCookie)))
            {
                if (ErrorHandler.Succeeded(shellMonitorSelection.IsCmdUIContextActive(fullyLoadedContextCookie, out var fActive)) && fActive != 0)
                {
                    _solutionLoadComplete = true;
                }
            }
        }
        internal override void SetDocumentContext(DocumentId documentId)
        {
            var hostDocument = GetHostDocument(documentId);
            var hierarchy    = hostDocument.Project.Hierarchy;
            var itemId       = hostDocument.GetItemId();

            if (itemId == (uint)VSConstants.VSITEMID.Nil)
            {
                // the document has been removed from the solution
                return;
            }

            var sharedHierarchy = LinkedFileUtilities.GetSharedHierarchyForItem(hierarchy, itemId);

            if (sharedHierarchy != null)
            {
                // Universal Project shared files
                //     Change the SharedItemContextHierarchy of the project's parent hierarchy, then
                //     hierarchy events will trigger the workspace to update.
                var hr = sharedHierarchy.SetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID7.VSHPROPID_SharedItemContextHierarchy, hierarchy);
            }
            else
            {
                // Regular linked files
                //     Transfer the item (open buffer) to the new hierarchy, and then hierarchy events
                //     will trigger the workspace to update.
                var vsproj = hierarchy as IVsProject3;
                var hr     = vsproj.TransferItem(hostDocument.FilePath, hostDocument.FilePath, punkWindowFrame: null);
            }
        }
            private void SubscribeToSharedHierarchyEvents(DocumentId documentId)
            {
                // Todo: maybe avoid double alerts.
                var hostDocument = _workspace.GetHostDocument(documentId);

                if (hostDocument == null)
                {
                    return;
                }

                var hierarchy = hostDocument.Project.Hierarchy;

                var itemId = hostDocument.GetItemId();

                if (itemId == (uint)VSConstants.VSITEMID.Nil)
                {
                    // the document has been removed from the solution
                    return;
                }

                var sharedHierarchy = LinkedFileUtilities.GetSharedHierarchyForItem(hierarchy, itemId);

                if (sharedHierarchy != null)
                {
                    uint cookie;
                    var  eventSink = new HierarchyEventsSink(_workspace, sharedHierarchy, documentId);
                    var  hr        = sharedHierarchy.AdviseHierarchyEvents(eventSink, out cookie);

                    if (hr == VSConstants.S_OK && !_documentIdToHierarchyEventsCookieMap.ContainsKey(documentId))
                    {
                        _documentIdToHierarchyEventsCookieMap.Add(documentId, cookie);
                    }
                }
            }
            private void UnsubscribeFromSharedHierarchyEvents(DocumentId documentId)
            {
                var hostDocument = _workspace.GetHostDocument(documentId);
                var hierarchy    = hostDocument.Project.Hierarchy;

                var itemId = hostDocument.GetItemId();

                if (itemId == (uint)VSConstants.VSITEMID.Nil)
                {
                    // the document has been removed from the solution
                    return;
                }

                var sharedHierarchy = LinkedFileUtilities.GetSharedHierarchyForItem(hierarchy, itemId);

                if (sharedHierarchy != null)
                {
                    uint cookie;
                    if (_documentIdToHierarchyEventsCookieMap.TryGetValue(documentId, out cookie))
                    {
                        var hr = sharedHierarchy.UnadviseHierarchyEvents(cookie);
                        _documentIdToHierarchyEventsCookieMap.Remove(documentId);
                    }
                }
            }
Example #6
0
        /// <summary>
        /// Creates a document provider.
        /// </summary>
        /// <param name="serviceProvider">Service provider</param>
        /// <param name="documentTrackingService">An optional <see cref="VisualStudioDocumentTrackingService"/> to track active and visible documents.</param>
        public DocumentProvider(
            VisualStudioProjectTracker projectTracker,
            IServiceProvider serviceProvider,
            VisualStudioDocumentTrackingService documentTrackingService,
            LinkedFileUtilities linkedFileUtilities)
            : base(projectTracker.ThreadingContext)
        {
            var componentModel = (IComponentModel)serviceProvider.GetService(typeof(SComponentModel));

            _projectTracker = projectTracker;
            this._documentTrackingServiceOpt   = documentTrackingService;
            this._runningDocumentTable         = (IVsRunningDocumentTable4)serviceProvider.GetService(typeof(SVsRunningDocumentTable));
            this._editorAdaptersFactoryService = componentModel.GetService <IVsEditorAdaptersFactoryService>();
            this._contentTypeRegistryService   = componentModel.GetService <IContentTypeRegistryService>();
            _linkedFileUtilities = linkedFileUtilities;
            _textManager         = (IVsTextManager)serviceProvider.GetService(typeof(SVsTextManager));

            _fileChangeService = (IVsFileChangeEx)serviceProvider.GetService(typeof(SVsFileChangeEx));

            var shell = (IVsShell)serviceProvider.GetService(typeof(SVsShell));

            if (shell == null)
            {
                // This can happen only in tests, bail out.
                return;
            }

            var runningDocumentTableForEvents = (IVsRunningDocumentTable)_runningDocumentTable;

            Marshal.ThrowExceptionForHR(runningDocumentTableForEvents.AdviseRunningDocTableEvents(new RunningDocTableEventsSink(this), out _runningDocumentTableEventCookie));
        }
Example #7
0
        private bool IsCurrentContext(DocumentKey documentKey)
        {
            AssertIsForeground();
            var document = documentKey.HostProject.GetCurrentDocumentFromPath(documentKey.Moniker);

            return(document != null && LinkedFileUtilities.IsCurrentContextHierarchy(document, _runningDocumentTable));
        }
Example #8
0
        internal void UpdateDocumentContextIfContainsDocument(IVsHierarchy sharedHierarchy, DocumentId documentId)
        {
            // TODO: This is a very roundabout way to update the context

            // The sharedHierarchy passed in has a new context, but we don't know what it is.
            // The documentId passed in is associated with this sharedHierarchy, and this method
            // will be called once for each such documentId. During this process, one of these
            // documentIds will actually belong to the new SharedItemContextHierarchy. Once we
            // find that one, we can map back to the open buffer and set its active context to
            // the appropriate project.

            // Note that if there is a single head project and it's in the process of being unloaded
            // there might not be a host project.
            var hostProject = LinkedFileUtilities.GetContextHostProject(sharedHierarchy, DeferredState.ProjectTracker);

            if (hostProject?.Hierarchy == sharedHierarchy)
            {
                return;
            }

            if (hostProject.Id != documentId.ProjectId)
            {
                // While this documentId is associated with one of the head projects for this
                // sharedHierarchy, it is not associated with the new context hierarchy. Another
                // documentId will be passed to this method and update the context.
                return;
            }

            // This documentId belongs to the new SharedItemContextHierarchy. Update the associated
            // buffer.
            OnDocumentContextUpdated(documentId);
        }
Example #9
0
        private bool IsCurrentContext(uint docCookie, DocumentKey documentKey)
        {
            AssertIsForeground();
            _runningDocumentTable.GetDocumentHierarchyItem(docCookie, out var hierarchy, out var itemid);

            // If it belongs to a Shared Code or ASP.NET 5 project, then find the correct host project
            var hostProject = LinkedFileUtilities.GetContextHostProject(hierarchy, _projectContainer);

            return(documentKey.HostProject == hostProject);
        }
Example #10
0
        /// <summary>
        /// Finds the <see cref="DocumentId"/> related to the given <see cref="DocumentId"/> that
        /// is in the current context. For regular files (non-shared and non-linked) and closed
        /// linked files, this is always the provided <see cref="DocumentId"/>. For open linked
        /// files and open shared files, the active context is already tracked by the
        /// <see cref="Workspace"/> and can be looked up directly. For closed shared files, the
        /// document in the shared project's <see cref="__VSHPROPID7.VSHPROPID_SharedItemContextHierarchy"/>
        /// is preferred.
        /// </summary>
        internal override DocumentId GetDocumentIdInCurrentContext(DocumentId documentId)
        {
            // If the document is open, then the Workspace knows the current context for both
            // linked and shared files
            if (IsDocumentOpen(documentId))
            {
                return(base.GetDocumentIdInCurrentContext(documentId));
            }

            var hostDocument = GetHostDocument(documentId);

            if (hostDocument == null)
            {
                // This can happen if the document was temporary and has since been closed/deleted.
                return(base.GetDocumentIdInCurrentContext(documentId));
            }

            var itemId = hostDocument.GetItemId();

            if (itemId == (uint)VSConstants.VSITEMID.Nil)
            {
                // An itemid is required to determine whether the file belongs to a Shared Project
                return(base.GetDocumentIdInCurrentContext(documentId));
            }

            // If this is a regular document or a closed linked (non-shared) document, then use the
            // default logic for determining current context.
            var sharedHierarchy = LinkedFileUtilities.GetSharedHierarchyForItem(hostDocument.Project.Hierarchy, itemId);

            if (sharedHierarchy == null)
            {
                return(base.GetDocumentIdInCurrentContext(documentId));
            }

            // This is a closed shared document, so we must determine the correct context.
            var hostProject     = LinkedFileUtilities.GetContextHostProject(sharedHierarchy, DeferredState.ProjectTracker);
            var matchingProject = CurrentSolution.GetProject(hostProject.Id);

            if (matchingProject == null || hostProject.Hierarchy == sharedHierarchy)
            {
                return(base.GetDocumentIdInCurrentContext(documentId));
            }

            if (matchingProject.ContainsDocument(documentId))
            {
                // The provided documentId is in the current context project
                return(documentId);
            }

            // The current context document is from another project.
            var linkedDocumentIds  = CurrentSolution.GetDocument(documentId).GetLinkedDocumentIds();
            var matchingDocumentId = linkedDocumentIds.FirstOrDefault(id => id.ProjectId == matchingProject.Id);

            return(matchingDocumentId ?? base.GetDocumentIdInCurrentContext(documentId));
        }
        public void AddAdditionalFile(string additionalFilePath)
        {
            var document = this.DocumentProvider.TryGetDocumentForFile(this, (uint)VSConstants.VSITEMID.Nil, filePath: additionalFilePath, sourceCodeKind: SourceCodeKind.Regular, canUseTextBuffer: (b) => true);

            if (document == null)
            {
                return;
            }

            AddAdditionalDocument(document,
                                  isCurrentContext: document.Project.Hierarchy == LinkedFileUtilities.GetContextHierarchy(document, RunningDocumentTable));
        }
Example #12
0
        private bool IsCurrentContext(uint docCookie, DocumentKey documentKey)
        {
            IVsHierarchy hierarchy;
            uint         itemid;

            RunningDocumentTable.GetDocumentHierarchyItem(docCookie, out hierarchy, out itemid);

            // If it belongs to a Shared Code project, then the current context is determined
            // by the SharedItemContextHierarchy.
            var hierarchyOwningDocument = LinkedFileUtilities.GetSharedItemContextHierarchy(hierarchy) ?? hierarchy;

            return(documentKey.HostProject.Hierarchy == hierarchyOwningDocument);
        }
Example #13
0
            public StandardTextDocument(
                DocumentProvider documentProvider,
                IVisualStudioHostProject project,
                DocumentKey documentKey,
                uint itemId,
                SourceCodeKind sourceCodeKind,
                ITextBufferFactoryService textBufferFactoryService,
                ITextUndoHistoryRegistry textUndoHistoryRegistry,
                IVsFileChangeEx fileChangeService,
                ITextBuffer openTextBuffer,
                DocumentId id)
            {
                Contract.ThrowIfNull(documentProvider);
                Contract.ThrowIfNull(textBufferFactoryService);

                this.Project = project;
                this.Id      = id ?? DocumentId.CreateNewId(project.Id, documentKey.Moniker);
                this.Folders = project.GetFolderNames(itemId);

                // TODO:
                // this one doesn't work for asynchronous project load situation where shared projects is loaded after one uses shared file.
                // we need to figure out what to do on those case. but this works for project k case.
                // opened an issue to track this issue - https://github.com/dotnet/roslyn/issues/1859
                this.SharedHierarchy = project.Hierarchy == null ? null : LinkedFileUtilities.GetSharedHierarchyForItem(project.Hierarchy, itemId);
                _documentProvider    = documentProvider;

                this.Key                          = documentKey;
                this.SourceCodeKind               = sourceCodeKind;
                _itemMoniker                      = documentKey.Moniker;
                _textBufferFactoryService         = textBufferFactoryService;
                _textUndoHistoryRegistry          = textUndoHistoryRegistry;
                _fileChangeTracker                = new FileChangeTracker(fileChangeService, this.FilePath);
                _fileChangeTracker.UpdatedOnDisk += OnUpdatedOnDisk;

                _openTextBuffer  = openTextBuffer;
                _snapshotTracker = new ReiteratedVersionSnapshotTracker(openTextBuffer);

                // The project system does not tell us the CodePage specified in the proj file, so
                // we use null to auto-detect.
                _doNotAccessDirectlyLoader = new FileTextLoader(documentKey.Moniker, defaultEncoding: null);

                // If we aren't already open in the editor, then we should create a file change notification
                if (openTextBuffer == null)
                {
                    _fileChangeTracker.StartFileChangeListeningAsync();
                }
            }
Example #14
0
            public StandardTextDocument(
                DocumentProvider documentProvider,
                IVisualStudioHostProject project,
                DocumentKey documentKey,
                uint itemId,
                SourceCodeKind sourceCodeKind,
                ITextBufferFactoryService textBufferFactoryService,
                ITextUndoHistoryRegistry textUndoHistoryRegistry,
                IVsFileChangeEx fileChangeService,
                ITextBuffer openTextBuffer,
                DocumentId id)
            {
                Contract.ThrowIfNull(documentProvider);
                Contract.ThrowIfNull(textBufferFactoryService);

                this.Project = project;
                this.Id      = id ?? DocumentId.CreateNewId(project.Id, documentKey.Moniker);
                this.Folders = project.GetFolderNames(itemId);

                this.SharedHierarchy = project.Hierarchy == null ? null : LinkedFileUtilities.GetSharedHierarchyForItem(project.Hierarchy, itemId);
                _documentProvider    = documentProvider;

                this.Key                          = documentKey;
                this.SourceCodeKind               = sourceCodeKind;
                _itemMoniker                      = documentKey.Moniker;
                _textBufferFactoryService         = textBufferFactoryService;
                _textUndoHistoryRegistry          = textUndoHistoryRegistry;
                _fileChangeTracker                = new FileChangeTracker(fileChangeService, this.FilePath);
                _fileChangeTracker.UpdatedOnDisk += OnUpdatedOnDisk;

                _openTextBuffer  = openTextBuffer;
                _snapshotTracker = new ReiteratedVersionSnapshotTracker(openTextBuffer);

                // The project system does not tell us the CodePage specified in the proj file, so
                // we use null to auto-detect.
                _doNotAccessDirectlyLoader = new FileTextLoader(documentKey.Moniker, defaultEncoding: null);

                // If we aren't already open in the editor, then we should create a file change notification
                if (openTextBuffer == null)
                {
                    _fileChangeTracker.StartFileChangeListeningAsync();
                }
            }
Example #15
0
            internal void StartPushingToWorkspaceAndNotifyOfOpenDocuments(
                IEnumerable <AbstractProject> projects)
            {
                AssertIsForeground();

                // If the workspace host isn't actually ready yet, we shouldn't do anything.
                // Also, if the solution is closing we shouldn't do anything either, because all of our state is
                // in the process of going away. This can happen if we receive notification that a document has
                // opened in the middle of the solution close operation.
                if (!this.HostReadyForEvents || _tracker._solutionIsClosing)
                {
                    return;
                }

                // We need to push these projects and any project dependencies we already know about. Therefore, compute the
                // transitive closure of the projects that haven't already been pushed, keeping them in appropriate order.
                var visited       = new HashSet <AbstractProject>();
                var inOrderToPush = new List <AbstractProject>();

                foreach (var project in projects)
                {
                    AddToPushListIfNeeded(project, inOrderToPush, visited);
                }

                var projectInfos = inOrderToPush.Select(p => p.CreateProjectInfoForCurrentState()).ToImmutableArray();

                // We need to enable projects to start pushing changes to workspace hosts even before we add the solution/project to the host.
                // This is required because between the point we capture the project info for current state and the point where we start pushing to workspace hosts,
                // project system may send new events on the AbstractProject on a background thread, and these won't get pushed over to the workspace hosts as we didn't set the _pushingChangesToWorkspaceHost flag on the AbstractProject.
                // By invoking StartPushingToWorkspaceHosts upfront, any project state changes on the background thread will enqueue notifications to workspace hosts on foreground scheduled tasks.
                foreach (var project in inOrderToPush)
                {
                    project.StartPushingToWorkspaceHosts();
                }

                if (!_solutionAdded)
                {
                    string       solutionFilePath = null;
                    VersionStamp?version          = default(VersionStamp?);
                    // Figure out the solution version
                    if (ErrorHandler.Succeeded(_tracker._vsSolution.GetSolutionInfo(out var solutionDirectory, out var solutionFileName, out var userOptsFile)) && solutionFileName != null)
                    {
                        solutionFilePath = Path.Combine(solutionDirectory, solutionFileName);
                        if (File.Exists(solutionFilePath))
                        {
                            version = VersionStamp.Create(File.GetLastWriteTimeUtc(solutionFilePath));
                        }
                    }

                    if (version == null)
                    {
                        version = VersionStamp.Create();
                    }

                    var id = SolutionId.CreateNewId(string.IsNullOrWhiteSpace(solutionFileName) ? null : solutionFileName);
                    _tracker.RegisterSolutionProperties(id);

                    var solutionInfo = SolutionInfo.Create(id, version.Value, solutionFilePath, projects: projectInfos);

                    this.Host.OnSolutionAdded(solutionInfo);

                    _solutionAdded = true;
                }
                else
                {
                    // The solution is already added, so we'll just do project added notifications from here
                    foreach (var projectInfo in projectInfos)
                    {
                        this.Host.OnProjectAdded(projectInfo);
                    }
                }

                foreach (var project in inOrderToPush)
                {
                    _pushedProjects.Add(project);

                    foreach (var document in project.GetCurrentDocuments())
                    {
                        if (document.IsOpen)
                        {
                            this.Host.OnDocumentOpened(
                                document.Id,
                                document.GetOpenTextBuffer(),
                                isCurrentContext: LinkedFileUtilities.IsCurrentContextHierarchy(document, _tracker._runningDocumentTable));
                        }
                    }
                }
            }
        /// <summary>
        /// Starts pushing events from the given projects to the workspace hosts and notifies about open documents.
        /// </summary>
        /// <remarks>This method must be called on the foreground thread.</remarks>
        internal void StartPushingToWorkspaceAndNotifyOfOpenDocuments(IEnumerable <AbstractProject> projects)
        {
            AssertIsForeground();

            // If the solution is closing we shouldn't do anything, because all of our state is
            // in the process of going away. This can happen if we receive notification that a document has
            // opened in the middle of the solution close operation.
            if (_solutionIsClosing)
            {
                return;
            }

            // We need to push these projects and any project dependencies we already know about. Therefore, compute the
            // transitive closure of the projects that haven't already been pushed, keeping them in appropriate order.
            var visited       = new HashSet <AbstractProject>();
            var inOrderToPush = new List <AbstractProject>();

            void addToInOrderToPush(AbstractProject project)
            {
                Contract.ThrowIfFalse(ContainsProject(project));

                // Bail out if any of the following is true:
                //  1. We have already started pushing changes for this project OR
                //  2. We have already visited this project in a prior recursive call
                if (_pushedProjects.Contains(project) || !visited.Add(project))
                {
                    return;
                }

                foreach (var projectReference in project.GetCurrentProjectReferences())
                {
                    addToInOrderToPush(GetProject(projectReference.ProjectId));
                }

                inOrderToPush.Add(project);
            }

            foreach (var project in projects)
            {
                addToInOrderToPush(project);
            }

            var projectInfos = inOrderToPush.Select(p => p.CreateProjectInfoForCurrentState()).ToImmutableArray();

            // We need to enable projects to start pushing changes to the workspace even before we add the solution/project to the host.
            // This is required because between the point we capture the project info for current state and the point where we start pushing to the workspace,
            // project system may send new events on the AbstractProject on a background thread, and these won't get pushed over to the workspace hosts as we didn't set the _pushingChangesToWorkspaceHost flag on the AbstractProject.
            // By invoking StartPushingToWorkspaceHosts upfront, any project state changes on the background thread will enqueue notifications to workspace hosts on foreground scheduled tasks.
            foreach (var project in inOrderToPush)
            {
                project.PushingChangesToWorkspace = true;

                Logger.Log(FunctionId.AbstractProject_PushedToWorkspace,
                           KeyValueLogMessage.Create(LogType.Trace, m =>
                {
                    m[AbstractProject.ProjectGuidPropertyName] = project.Guid;
                }));
            }

            using (WorkspaceServices.GetService <IGlobalOperationNotificationService>()?.Start("Add Project to Workspace"))
            {
                if (!_solutionAdded)
                {
                    string       solutionFilePath = null;
                    VersionStamp?version          = default;
                    // Figure out the solution version
                    if (ErrorHandler.Succeeded(_vsSolution.GetSolutionInfo(out var solutionDirectory, out var solutionFileName, out var userOptsFile)) && solutionFileName != null)
                    {
                        solutionFilePath = Path.Combine(solutionDirectory, solutionFileName);
                        if (File.Exists(solutionFilePath))
                        {
                            version = VersionStamp.Create(File.GetLastWriteTimeUtc(solutionFilePath));
                        }
                    }

                    if (version == null)
                    {
                        version = VersionStamp.Create();
                    }

                    var id = SolutionId.CreateNewId(string.IsNullOrWhiteSpace(solutionFileName) ? null : solutionFileName);

                    var solutionInfo = SolutionInfo.Create(id, version.Value, solutionFilePath, projects: projectInfos);

                    NotifyWorkspace(workspace => workspace.OnSolutionAdded(solutionInfo));

                    _solutionAdded = true;

                    var persistenceService = WorkspaceServices.GetRequiredService <IPersistentStorageLocationService>() as VisualStudioPersistentStorageLocationService;
                    persistenceService?.UpdateForVisualStudioWorkspace(_workspace);
                }
                else
                {
                    // The solution is already added, so we'll just do project added notifications from here
                    foreach (var projectInfo in projectInfos)
                    {
                        NotifyWorkspace(workspace => workspace.OnProjectAdded(projectInfo));
                    }
                }

                foreach (var project in inOrderToPush)
                {
                    _pushedProjects.Add(project);

                    foreach (var document in project.GetCurrentDocuments())
                    {
                        if (document.IsOpen)
                        {
                            NotifyWorkspace(workspace =>
                            {
                                workspace.OnDocumentOpened(
                                    document.Id,
                                    document.GetOpenTextBuffer().AsTextContainer(),
                                    isCurrentContext: LinkedFileUtilities.IsCurrentContextHierarchy(document, _runningDocumentTable));
                                (workspace as VisualStudioWorkspaceImpl)?.ConnectToSharedHierarchyEvents(document);
                            });
                        }
                    }
                }
            }
        }
Example #17
0
            public DeferredInitializationState(IThreadingContext threadingContext, VisualStudioWorkspaceImpl workspace, IServiceProvider serviceProvider, LinkedFileUtilities linkedFileUtilities)
                : base(threadingContext, assertIsForeground: true)
            {
                ServiceProvider          = serviceProvider;
                ShellOpenDocumentService = (IVsUIShellOpenDocument)serviceProvider.GetService(typeof(SVsUIShellOpenDocument));
                ProjectTracker           = new VisualStudioProjectTracker(threadingContext, serviceProvider, workspace, linkedFileUtilities);

                // Ensure the document tracking service is initialized on the UI thread
                var documentTrackingService   = (VisualStudioDocumentTrackingService)workspace.Services.GetService <IDocumentTrackingService>();
                var documentProvider          = new DocumentProvider(ProjectTracker, serviceProvider, documentTrackingService, linkedFileUtilities);
                var metadataReferenceProvider = workspace.Services.GetService <VisualStudioMetadataReferenceManager>();
                var ruleSetFileProvider       = workspace.Services.GetService <VisualStudioRuleSetManager>();

                ProjectTracker.InitializeProviders(documentProvider, metadataReferenceProvider, ruleSetFileProvider);

                var componentModel    = (IComponentModel)serviceProvider.GetService(typeof(SComponentModel));
                var saveEventsService = componentModel.GetService <SaveEventsService>();

                saveEventsService.StartSendingSaveEvents();

                VisualStudioProjectCacheHostServiceFactory.ConnectProjectCacheServiceToDocumentTracking(workspace.Services, (ProjectCacheService)workspace.CurrentSolution.Services.CacheService);

                // Ensure the options factory services are initialized on the UI thread
                workspace.Services.GetService <IOptionService>();
            }