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 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); } } }
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); } } }
/// <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 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(); } }
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(); } }