private void RegisterDesignerAttribute(VisualStudioWorkspaceImpl workspace, DocumentId documentId, string designerAttributeArgument) { if (workspace == null) { return; } _notificationService.RegisterNotification(() => { var vsDocument = workspace.GetHostDocument(documentId); if (vsDocument == null) { return; } uint itemId = vsDocument.GetItemId(); if (itemId == (uint)VSConstants.VSITEMID.Nil) { // it is no longer part of the solution return; } object currentValue; if (ErrorHandler.Succeeded(vsDocument.Project.Hierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_ItemSubType, out currentValue))) { var currentStringValue = string.IsNullOrEmpty(currentValue as string) ? null : (string)currentValue; if (string.Equals(currentStringValue, designerAttributeArgument, StringComparison.OrdinalIgnoreCase)) { // PERF: Avoid sending the message if the project system already has the current value. return; } } try { var designer = GetDesignerFromForegroundThread(); if (designer != null) { designer.RegisterDesignViewAttribute(vsDocument.Project.Hierarchy, (int)itemId, dwClass: 0, pwszAttributeValue: designerAttributeArgument); } } catch { // DevDiv # 933717 // turns out RegisterDesignViewAttribute can throw in certain cases such as a file failed to be checked out by source control // or IVSHierarchy failed to set a property for this project // // just swallow it. don't crash VS. } }, _listener.BeginAsyncOperation("RegisterDesignerAttribute")); }
public static bool TryGetImageListAndIndex(this VisualStudioWorkspaceImpl workspace, IVsImageService2 imageService, DocumentId id, out IntPtr imageList, out ushort index) { var hostDocument = workspace.GetHostDocument(id); if (hostDocument != null) { var hierarchy = hostDocument.Project.Hierarchy; var itemId = hostDocument.GetItemId(); return(TryGetImageListAndIndex(hierarchy, imageService, itemId, out imageList, out index)); } imageList = default(IntPtr); index = 0; return(false); }
private static bool TryAdjustSpanIfNeededForVenus(VisualStudioWorkspaceImpl workspace, DocumentId documentId, int originalLine, int originalColumn, out MappedSpan mappedSpan) { mappedSpan = default(MappedSpan); if (documentId == null) { return(false); } var containedDocument = workspace.GetHostDocument(documentId) as ContainedDocument; if (containedDocument == null) { return(false); } var originalSpanOnSecondaryBuffer = new TextManager.Interop.TextSpan() { iStartLine = originalLine, iStartIndex = originalColumn, iEndLine = originalLine, iEndIndex = originalColumn }; var containedLanguage = containedDocument.ContainedLanguage; var bufferCoordinator = containedLanguage.BufferCoordinator; var containedLanguageHost = containedLanguage.ContainedLanguageHost; var spansOnPrimaryBuffer = new TextManager.Interop.TextSpan[1]; if (VSConstants.S_OK == bufferCoordinator.MapSecondaryToPrimarySpan(originalSpanOnSecondaryBuffer, spansOnPrimaryBuffer)) { // easy case, we can map span in subject buffer to surface buffer. no need to adjust any span mappedSpan = new MappedSpan(originalLine, originalColumn, spansOnPrimaryBuffer[0].iStartLine, spansOnPrimaryBuffer[0].iStartIndex); return(true); } // we can't directly map span in subject buffer to surface buffer. see whether there is any visible span we can use from the subject buffer span if (containedLanguageHost != null && VSConstants.S_OK != containedLanguageHost.GetNearestVisibleToken(originalSpanOnSecondaryBuffer, spansOnPrimaryBuffer)) { // no visible span we can use. return(false); } // We need to map both the original and mapped location into visible code so that features such as error list, squiggle, etc. points to user visible area // We have the mapped location in the primary buffer. var nearestVisibleSpanOnPrimaryBuffer = new TextManager.Interop.TextSpan() { iStartLine = spansOnPrimaryBuffer[0].iStartLine, iStartIndex = spansOnPrimaryBuffer[0].iStartIndex, iEndLine = spansOnPrimaryBuffer[0].iStartLine, iEndIndex = spansOnPrimaryBuffer[0].iStartIndex }; // Map this location back to the secondary span to re-adjust the original location to be in user-code in secondary buffer. var spansOnSecondaryBuffer = new TextManager.Interop.TextSpan[1]; if (VSConstants.S_OK != bufferCoordinator.MapPrimaryToSecondarySpan(nearestVisibleSpanOnPrimaryBuffer, spansOnSecondaryBuffer)) { // we can't adjust original position but we can adjust mapped one mappedSpan = new MappedSpan(originalLine, originalColumn, nearestVisibleSpanOnPrimaryBuffer.iStartLine, nearestVisibleSpanOnPrimaryBuffer.iStartIndex); return(true); } var nearestVisibleSpanOnSecondaryBuffer = spansOnSecondaryBuffer[0]; var originalLocationMovedAboveInFile = IsOriginalLocationMovedAboveInFile(originalLine, originalColumn, nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex); if (!originalLocationMovedAboveInFile) { mappedSpan = new MappedSpan(nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex, nearestVisibleSpanOnPrimaryBuffer.iStartLine, nearestVisibleSpanOnPrimaryBuffer.iStartIndex); return(true); } LinePosition adjustedPosition; if (TryFixUpNearestVisibleSpan(containedLanguageHost, bufferCoordinator, nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex, out adjustedPosition)) { // span has changed yet again, re-calculate span return(TryAdjustSpanIfNeededForVenus(workspace, documentId, adjustedPosition.Line, adjustedPosition.Character, out mappedSpan)); } mappedSpan = new MappedSpan(nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex, nearestVisibleSpanOnPrimaryBuffer.iStartLine, nearestVisibleSpanOnPrimaryBuffer.iStartIndex); return(true); }
private static bool TryAdjustSpanIfNeededForVenus(VisualStudioWorkspaceImpl workspace, DocumentId documentId, int originalLine, int originalColumn, out MappedSpan mappedSpan) { mappedSpan = default(MappedSpan); if (documentId == null) { return false; } var containedDocument = workspace.GetHostDocument(documentId) as ContainedDocument; if (containedDocument == null) { return false; } var originalSpanOnSecondaryBuffer = new TextManager.Interop.TextSpan() { iStartLine = originalLine, iStartIndex = originalColumn, iEndLine = originalLine, iEndIndex = originalColumn }; var containedLanguage = containedDocument.ContainedLanguage; var bufferCoordinator = containedLanguage.BufferCoordinator; var containedLanguageHost = containedLanguage.ContainedLanguageHost; var spansOnPrimaryBuffer = new TextManager.Interop.TextSpan[1]; if (VSConstants.S_OK == bufferCoordinator.MapSecondaryToPrimarySpan(originalSpanOnSecondaryBuffer, spansOnPrimaryBuffer)) { // easy case, we can map span in subject buffer to surface buffer. no need to adjust any span mappedSpan = new MappedSpan(originalLine, originalColumn, spansOnPrimaryBuffer[0].iStartLine, spansOnPrimaryBuffer[0].iStartIndex); return true; } // we can't directly map span in subject buffer to surface buffer. see whether there is any visible span we can use from the subject buffer span if (containedLanguageHost != null && VSConstants.S_OK != containedLanguageHost.GetNearestVisibleToken(originalSpanOnSecondaryBuffer, spansOnPrimaryBuffer)) { // no visible span we can use. return false; } // We need to map both the original and mapped location into visible code so that features such as error list, squiggle, etc. points to user visible area // We have the mapped location in the primary buffer. var nearestVisibleSpanOnPrimaryBuffer = new TextManager.Interop.TextSpan() { iStartLine = spansOnPrimaryBuffer[0].iStartLine, iStartIndex = spansOnPrimaryBuffer[0].iStartIndex, iEndLine = spansOnPrimaryBuffer[0].iStartLine, iEndIndex = spansOnPrimaryBuffer[0].iStartIndex }; // Map this location back to the secondary span to re-adjust the original location to be in user-code in secondary buffer. var spansOnSecondaryBuffer = new TextManager.Interop.TextSpan[1]; if (VSConstants.S_OK != bufferCoordinator.MapPrimaryToSecondarySpan(nearestVisibleSpanOnPrimaryBuffer, spansOnSecondaryBuffer)) { // we can't adjust original position but we can adjust mapped one mappedSpan = new MappedSpan(originalLine, originalColumn, nearestVisibleSpanOnPrimaryBuffer.iStartLine, nearestVisibleSpanOnPrimaryBuffer.iStartIndex); return true; } var nearestVisibleSpanOnSecondaryBuffer = spansOnSecondaryBuffer[0]; var originalLocationMovedAboveInFile = IsOriginalLocationMovedAboveInFile(originalLine, originalColumn, nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex); if (!originalLocationMovedAboveInFile) { mappedSpan = new MappedSpan(nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex, nearestVisibleSpanOnPrimaryBuffer.iStartLine, nearestVisibleSpanOnPrimaryBuffer.iStartIndex); return true; } if (TryFixUpNearestVisibleSpan(containedLanguageHost, bufferCoordinator, nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex, out var adjustedPosition)) { // span has changed yet again, re-calculate span return TryAdjustSpanIfNeededForVenus(workspace, documentId, adjustedPosition.Line, adjustedPosition.Character, out mappedSpan); } mappedSpan = new MappedSpan(nearestVisibleSpanOnSecondaryBuffer.iStartLine, nearestVisibleSpanOnSecondaryBuffer.iStartIndex, nearestVisibleSpanOnPrimaryBuffer.iStartLine, nearestVisibleSpanOnPrimaryBuffer.iStartIndex); return true; }