1*06f32e7eSjoerg using EnvDTE;
2*06f32e7eSjoerg using Microsoft.VisualStudio.Editor;
3*06f32e7eSjoerg using Microsoft.VisualStudio.Shell;
4*06f32e7eSjoerg using Microsoft.VisualStudio.Shell.Interop;
5*06f32e7eSjoerg using Microsoft.VisualStudio.Text;
6*06f32e7eSjoerg using Microsoft.VisualStudio.Text.Editor;
7*06f32e7eSjoerg using Microsoft.VisualStudio.TextManager.Interop;
8*06f32e7eSjoerg using System;
9*06f32e7eSjoerg using System.IO;
10*06f32e7eSjoerg 
11*06f32e7eSjoerg namespace LLVM.ClangFormat
12*06f32e7eSjoerg {
13*06f32e7eSjoerg     internal sealed class Vsix
14*06f32e7eSjoerg     {
15*06f32e7eSjoerg         /// <summary>
16*06f32e7eSjoerg         /// Returns the currently active view if it is a IWpfTextView.
17*06f32e7eSjoerg         /// </summary>
GetCurrentView()18*06f32e7eSjoerg         public static IWpfTextView GetCurrentView()
19*06f32e7eSjoerg         {
20*06f32e7eSjoerg             // The SVsTextManager is a service through which we can get the active view.
21*06f32e7eSjoerg             var textManager = (IVsTextManager)Package.GetGlobalService(typeof(SVsTextManager));
22*06f32e7eSjoerg             IVsTextView textView;
23*06f32e7eSjoerg             textManager.GetActiveView(1, null, out textView);
24*06f32e7eSjoerg 
25*06f32e7eSjoerg             // Now we have the active view as IVsTextView, but the text interfaces we need
26*06f32e7eSjoerg             // are in the IWpfTextView.
27*06f32e7eSjoerg             return VsToWpfTextView(textView);
28*06f32e7eSjoerg         }
29*06f32e7eSjoerg 
IsDocumentDirty(Document document)30*06f32e7eSjoerg         public static bool IsDocumentDirty(Document document)
31*06f32e7eSjoerg         {
32*06f32e7eSjoerg             var textView = GetDocumentView(document);
33*06f32e7eSjoerg             var textDocument = GetTextDocument(textView);
34*06f32e7eSjoerg             return textDocument?.IsDirty == true;
35*06f32e7eSjoerg         }
36*06f32e7eSjoerg 
GetDocumentView(Document document)37*06f32e7eSjoerg         public static IWpfTextView GetDocumentView(Document document)
38*06f32e7eSjoerg         {
39*06f32e7eSjoerg             var textView = GetVsTextViewFrompPath(document.FullName);
40*06f32e7eSjoerg             return VsToWpfTextView(textView);
41*06f32e7eSjoerg         }
42*06f32e7eSjoerg 
VsToWpfTextView(IVsTextView textView)43*06f32e7eSjoerg         public static IWpfTextView VsToWpfTextView(IVsTextView textView)
44*06f32e7eSjoerg         {
45*06f32e7eSjoerg             var userData = (IVsUserData)textView;
46*06f32e7eSjoerg             if (userData == null)
47*06f32e7eSjoerg                 return null;
48*06f32e7eSjoerg             Guid guidWpfViewHost = DefGuidList.guidIWpfTextViewHost;
49*06f32e7eSjoerg             object host;
50*06f32e7eSjoerg             userData.GetData(ref guidWpfViewHost, out host);
51*06f32e7eSjoerg             return ((IWpfTextViewHost)host).TextView;
52*06f32e7eSjoerg         }
53*06f32e7eSjoerg 
GetVsTextViewFrompPath(string filePath)54*06f32e7eSjoerg         public static IVsTextView GetVsTextViewFrompPath(string filePath)
55*06f32e7eSjoerg         {
56*06f32e7eSjoerg             // From http://stackoverflow.com/a/2427368/4039972
57*06f32e7eSjoerg             var dte2 = (EnvDTE80.DTE2)Package.GetGlobalService(typeof(SDTE));
58*06f32e7eSjoerg             var sp = (Microsoft.VisualStudio.OLE.Interop.IServiceProvider)dte2;
59*06f32e7eSjoerg             var serviceProvider = new Microsoft.VisualStudio.Shell.ServiceProvider(sp);
60*06f32e7eSjoerg 
61*06f32e7eSjoerg             IVsUIHierarchy uiHierarchy;
62*06f32e7eSjoerg             uint itemID;
63*06f32e7eSjoerg             IVsWindowFrame windowFrame;
64*06f32e7eSjoerg             if (VsShellUtilities.IsDocumentOpen(serviceProvider, filePath, Guid.Empty,
65*06f32e7eSjoerg                 out uiHierarchy, out itemID, out windowFrame))
66*06f32e7eSjoerg             {
67*06f32e7eSjoerg                 // Get the IVsTextView from the windowFrame.
68*06f32e7eSjoerg                 return VsShellUtilities.GetTextView(windowFrame);
69*06f32e7eSjoerg             }
70*06f32e7eSjoerg             return null;
71*06f32e7eSjoerg         }
72*06f32e7eSjoerg 
GetTextDocument(IWpfTextView view)73*06f32e7eSjoerg         public static ITextDocument GetTextDocument(IWpfTextView view)
74*06f32e7eSjoerg         {
75*06f32e7eSjoerg             ITextDocument document;
76*06f32e7eSjoerg             if (view != null && view.TextBuffer.Properties.TryGetProperty(typeof(ITextDocument), out document))
77*06f32e7eSjoerg                 return document;
78*06f32e7eSjoerg             return null;
79*06f32e7eSjoerg         }
80*06f32e7eSjoerg 
GetDocumentParent(IWpfTextView view)81*06f32e7eSjoerg         public static string GetDocumentParent(IWpfTextView view)
82*06f32e7eSjoerg         {
83*06f32e7eSjoerg             ITextDocument document = GetTextDocument(view);
84*06f32e7eSjoerg             if (document != null)
85*06f32e7eSjoerg             {
86*06f32e7eSjoerg                 return Directory.GetParent(document.FilePath).ToString();
87*06f32e7eSjoerg             }
88*06f32e7eSjoerg             return null;
89*06f32e7eSjoerg         }
90*06f32e7eSjoerg 
GetDocumentPath(IWpfTextView view)91*06f32e7eSjoerg         public static string GetDocumentPath(IWpfTextView view)
92*06f32e7eSjoerg         {
93*06f32e7eSjoerg             return GetTextDocument(view)?.FilePath;
94*06f32e7eSjoerg         }
95*06f32e7eSjoerg     }
96*06f32e7eSjoerg }
97