@@ -66,12 +66,21 @@ public GitHubContextService(IGitHubServiceProvider serviceProvider, IGitService
6666 textManager = new Lazy < IVsTextManager2 > ( ( ) => serviceProvider . GetService < SVsTextManager , IVsTextManager2 > ( ) ) ;
6767 }
6868
69+ /// <summary>
70+ /// Find the context from a URL in the clipboard if any.
71+ /// </summary>
72+ /// <returns>The context or null if clipboard doesn't contain a GitHub URL</returns>
6973 public GitHubContext FindContextFromClipboard ( )
7074 {
7175 var text = Clipboard . GetText ( TextDataFormat . Text ) ;
7276 return FindContextFromUrl ( text ) ;
7377 }
7478
79+ /// <summary>
80+ /// Convert a GitHub URL to a context object.
81+ /// </summary>
82+ /// <param name="url">A GitHub URL</param>
83+ /// <returns>The context from the URL or null</returns>
7584 public GitHubContext FindContextFromUrl ( string url )
7685 {
7786 var uri = new UriString ( url ) ;
@@ -117,6 +126,10 @@ public GitHubContext FindContextFromUrl(string url)
117126 return context ;
118127 }
119128
129+ /// <summary>
130+ /// Find the context from the title of the topmost browser.
131+ /// </summary>
132+ /// <returns>A context or null if a context can't be found.</returns>
120133 public GitHubContext FindContextFromBrowser ( )
121134 {
122135 return
@@ -126,31 +139,23 @@ public GitHubContext FindContextFromBrowser()
126139 . FirstOrDefault ( ) ;
127140 }
128141
129- public IEnumerable < string > FindWindowTitlesForClass ( string className = "MozillaWindowClass" )
130- {
131- IntPtr handleWin = IntPtr . Zero ;
132- while ( IntPtr . Zero != ( handleWin = User32 . FindWindowEx ( IntPtr . Zero , handleWin , className , IntPtr . Zero ) ) )
133- {
134- // Allocate correct string length first
135- int length = User32 . GetWindowTextLength ( handleWin ) ;
136- if ( length == 0 )
137- {
138- continue ;
139- }
140-
141- var titleBuilder = new StringBuilder ( length + 1 ) ;
142- User32 . GetWindowText ( handleWin , titleBuilder , titleBuilder . Capacity ) ;
143- yield return titleBuilder . ToString ( ) ;
144- }
145- }
146-
142+ /// <summary>
143+ /// Convert a context to a repository URL.
144+ /// </summary>
145+ /// <param name="context">The context to convert.</param>
146+ /// <returns>A repository URL</returns>
147147 public Uri ToRepositoryUrl ( GitHubContext context )
148148 {
149149 var builder = new UriBuilder ( "https" , context . Host ?? "github.com" ) ;
150150 builder . Path = $ "{ context . Owner } /{ context . RepositoryName } ";
151151 return builder . Uri ;
152152 }
153153
154+ /// <summary>
155+ /// Find a context from a browser window title.
156+ /// </summary>
157+ /// <param name="windowTitle">A browser window title.</param>
158+ /// <returns>The context or null if none can be found</returns>
154159 public GitHubContext FindContextFromWindowTitle ( string windowTitle )
155160 {
156161 var match = windowTitleBlobRegex . Match ( windowTitle ) ;
@@ -237,6 +242,12 @@ public GitHubContext FindContextFromWindowTitle(string windowTitle)
237242 return null ;
238243 }
239244
245+ /// <summary>
246+ /// Open a file in the working directory that corresponds to a context and navigate to a line/range.
247+ /// </summary>
248+ /// <param name="repositoryDir">The working directory.</param>
249+ /// <param name="context">A context to navigate to.</param>
250+ /// <returns>True if navigation was successful</returns>
240251 public bool TryOpenFile ( string repositoryDir , GitHubContext context )
241252 {
242253 var ( commitish , path , isSha ) = ResolveBlob ( repositoryDir , context ) ;
@@ -251,6 +262,13 @@ public bool TryOpenFile(string repositoryDir, GitHubContext context)
251262 return true ;
252263 }
253264
265+ /// <summary>
266+ /// Map from a context to a repository blob object.
267+ /// </summary>
268+ /// <param name="repositoryDir">The target repository.</param>
269+ /// <param name="context">The context to map from.</param>
270+ /// <param name="remoteName">The name of the remote to search for branches.</param>
271+ /// <returns>The resolved commit-ish, blob path and commit SHA for the blob. Path will be null if the commit-ish can be resolved but not the blob.</returns>
254272 public ( string commitish , string path , string commitSha ) ResolveBlob ( string repositoryDir , GitHubContext context , string remoteName = "origin" )
255273 {
256274 Guard . ArgumentNotNull ( repositoryDir , nameof ( repositoryDir ) ) ;
@@ -316,6 +334,16 @@ public bool TryOpenFile(string repositoryDir, GitHubContext context)
316334 }
317335 }
318336
337+ /// <summary>
338+ /// Check if a file in the working directory has changed since a specified commit-ish.
339+ /// </summary>
340+ /// <remarks>
341+ /// The commit-ish might be a commit SHA, a tag or a remote branch.
342+ /// </remarks>
343+ /// <param name="repositoryDir">The target repository.</param>
344+ /// <param name="commitish">A commit SHA, remote branch or tag.</param>
345+ /// <param name="path">The path for a blob.</param>
346+ /// <returns>True if the working file is different.</returns>
319347 public bool HasChangesInWorkingDirectory ( string repositoryDir , string commitish , string path )
320348 {
321349 using ( var repo = gitService . GetRepository ( repositoryDir ) )
@@ -327,6 +355,17 @@ public bool HasChangesInWorkingDirectory(string repositoryDir, string commitish,
327355 }
328356 }
329357
358+ /// <summary>
359+ /// Attempt to open the Blame/Annotate view for a context.
360+ /// </summary>
361+ /// <remarks>
362+ /// The access to the Blame/Annotate view was added in a version of Visual Studio 2017. This method will return
363+ /// false is this functionality isn't available.
364+ /// </remarks>
365+ /// <param name="repositoryDir">The target repository</param>
366+ /// <param name="currentBranch">A branch in the local repository. It isn't displayed on the UI but must exist. It can be a remote or local branch.</param>
367+ /// <param name="context">The context to open.</param>
368+ /// <returns>True if AnnotateFile functionality is available.</returns>
330369 public async Task < bool > TryAnnotateFile ( string repositoryDir , string currentBranch , GitHubContext context )
331370 {
332371 var ( commitish , path , commitSha ) = ResolveBlob ( repositoryDir , context ) ;
@@ -371,7 +410,7 @@ IVsTextView FindActiveView()
371410 /// <param name="branchName">A branch of the target repository</param>
372411 /// <param name="relativePath">A path the the target blob</param>
373412 /// <param name="versionSha">The commit version of the blob</param>
374- /// <returns></returns>
413+ /// <returns>True if AnnotateFile functionality is available. </returns>
375414 bool AnnotateFile ( string repositoryPath , string branchName , string relativePath , string versionSha )
376415 {
377416 var serviceType = Type . GetType ( "Microsoft.VisualStudio.TeamFoundation.Git.Extensibility.IGitExt2, Microsoft.TeamFoundation.Git.Provider" , false ) ;
@@ -485,6 +524,24 @@ static string FindSubPath(UriString gitHubUrl, string matchPath)
485524 return path ;
486525 }
487526
527+ static IEnumerable < string > FindWindowTitlesForClass ( string className )
528+ {
529+ IntPtr handleWin = IntPtr . Zero ;
530+ while ( IntPtr . Zero != ( handleWin = User32 . FindWindowEx ( IntPtr . Zero , handleWin , className , IntPtr . Zero ) ) )
531+ {
532+ // Allocate correct string length first
533+ int length = User32 . GetWindowTextLength ( handleWin ) ;
534+ if ( length == 0 )
535+ {
536+ continue ;
537+ }
538+
539+ var titleBuilder = new StringBuilder ( length + 1 ) ;
540+ User32 . GetWindowText ( handleWin , titleBuilder , titleBuilder . Capacity ) ;
541+ yield return titleBuilder . ToString ( ) ;
542+ }
543+ }
544+
488545 static class User32
489546 {
490547 [ DllImport ( "user32.dll" , SetLastError = true ) ]
0 commit comments