Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 0fc10b7

Browse files
committed
Highlight line when single line is selected
Previously highlighting only worked when a range was selected. Use VsShellUtilities.OpenDocument instead of DTE.ItemOperations.OpenFile. Factor TryOpenFile into GitHubContextService.
1 parent 0aae4ca commit 0fc10b7

File tree

3 files changed

+88
-65
lines changed

3 files changed

+88
-65
lines changed

src/GitHub.App/Services/GitHubContextService.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
using System;
2+
using System.IO;
23
using System.Text;
34
using System.Linq;
45
using System.Collections.Generic;
56
using System.ComponentModel.Composition;
67
using System.Text.RegularExpressions;
78
using System.Runtime.InteropServices;
89
using GitHub.Primitives;
10+
using Microsoft.VisualStudio;
11+
using Microsoft.VisualStudio.Shell;
12+
using Microsoft.VisualStudio.Shell.Interop;
13+
using Microsoft.VisualStudio.TextManager.Interop;
914

1015
namespace GitHub.App.Services
1116
{
1217
[Export(typeof(GitHubContextService))]
1318
public class GitHubContextService
1419
{
20+
readonly IServiceProvider serviceProvider;
21+
1522
// USERID_REGEX = /[a-z0-9][a-z0-9\-\_]*/i
1623
const string owner = "(?<owner>[a-zA-Z0-9][a-zA-Z0-9-_]*)";
1724

@@ -37,6 +44,12 @@ public class GitHubContextService
3744

3845
static readonly Regex urlLineRegex = new Regex($"#L(?<line>[0-9]+)(-L(?<lineEnd>[0-9]+))?$", RegexOptions.Compiled);
3946

47+
[ImportingConstructor]
48+
public GitHubContextService([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider)
49+
{
50+
this.serviceProvider = serviceProvider;
51+
}
52+
4053
public GitHubContext FindContextFromUrl(string url)
4154
{
4255
var uri = new UriString(url);
@@ -116,6 +129,53 @@ public GitHubContext FindContextFromWindowTitle(string windowTitle)
116129
};
117130
}
118131

132+
public bool TryOpenFile(GitHubContext context, string repositoryDir)
133+
{
134+
var path = context.Path;
135+
if (path == null)
136+
{
137+
return false;
138+
}
139+
140+
var windowsPath = path.Replace('/', '\\');
141+
var fullPath = Path.Combine(repositoryDir, windowsPath);
142+
if (!File.Exists(fullPath))
143+
{
144+
// Search by filename only
145+
var fileName = Path.GetFileName(path);
146+
fullPath = Directory.EnumerateFiles(repositoryDir, fileName, SearchOption.AllDirectories).FirstOrDefault();
147+
}
148+
149+
if (fullPath == null)
150+
{
151+
return false;
152+
}
153+
154+
var textView = OpenDocument(fullPath);
155+
156+
var line = context.Line;
157+
if (line != null)
158+
{
159+
var lineEnd = context.LineEnd ?? line;
160+
161+
ErrorHandler.ThrowOnFailure(textView.SetSelection(line.Value - 1, 0, lineEnd.Value, 0));
162+
ErrorHandler.ThrowOnFailure(textView.CenterLines(line.Value - 1, lineEnd.Value - line.Value + 1));
163+
}
164+
165+
return true;
166+
}
167+
168+
IVsTextView OpenDocument(string fullPath)
169+
{
170+
var logicalView = VSConstants.LOGVIEWID.TextView_guid;
171+
IVsUIHierarchy hierarchy;
172+
uint itemID;
173+
IVsWindowFrame windowFrame;
174+
IVsTextView view;
175+
VsShellUtilities.OpenDocument(serviceProvider, fullPath, logicalView, out hierarchy, out itemID, out windowFrame, out view);
176+
return view;
177+
}
178+
119179
static (bool success, string owner, string repo, string branch, int? pullRequest, int? issue, string path) MatchWindowTitle(string windowTitle)
120180
{
121181
var match = windowTitlePathRegex.Match(windowTitle);

src/GitHub.VisualStudio/Commands/OpenFromUrlCommand.cs

Lines changed: 1 addition & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public override async Task Execute(string url)
125125
}
126126

127127
await TryOpenPullRequest(context);
128-
TryOpenFile(context, repositoryDir);
128+
gitHubContextService.Value.TryOpenFile(context, repositoryDir);
129129
}
130130

131131
VSConstants.MessageBoxResult ShowInfoMessage(string message)
@@ -165,50 +165,6 @@ static string FindSolutionDirectory(Solution solution)
165165
return null;
166166
}
167167

168-
bool TryOpenFile(GitHubContext context, string repositoryDir)
169-
{
170-
var path = context.Path;
171-
if (path == null)
172-
{
173-
return false;
174-
}
175-
176-
var windowsPath = path.Replace('/', '\\');
177-
var fullPath = Path.Combine(repositoryDir, windowsPath);
178-
if (!File.Exists(fullPath))
179-
{
180-
// Search by filename only
181-
var fileName = Path.GetFileName(path);
182-
fullPath = Directory.EnumerateFiles(repositoryDir, fileName, SearchOption.AllDirectories).FirstOrDefault();
183-
}
184-
185-
if (fullPath == null)
186-
{
187-
return false;
188-
}
189-
190-
dte.Value.ItemOperations.OpenFile(fullPath);
191-
192-
var line = context.Line;
193-
var lineEnd = context.LineEnd;
194-
if (line != null)
195-
{
196-
var activeView = pullRequestEditorService.Value.FindActiveView();
197-
if (lineEnd != null)
198-
{
199-
ErrorHandler.ThrowOnFailure(activeView.SetSelection(line.Value - 1, 0, lineEnd.Value, 0));
200-
ErrorHandler.ThrowOnFailure(activeView.CenterLines(line.Value - 1, lineEnd.Value - line.Value));
201-
}
202-
else
203-
{
204-
ErrorHandler.ThrowOnFailure(activeView.SetCaretPos(line.Value - 1, 0));
205-
ErrorHandler.ThrowOnFailure(activeView.CenterLines(line.Value - 1, 1));
206-
}
207-
}
208-
209-
return true;
210-
}
211-
212168
async Task<bool> TryOpenPullRequest(GitHubContext context)
213169
{
214170
var pullRequest = context.PullRequest;

test/GitHub.App.UnitTests/Services/GitHubContextServiceTests.cs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using GitHub.App.Services;
3+
using NSubstitute;
34
using NUnit.Framework;
45

56
public class GitHubContextServiceTests
@@ -12,7 +13,7 @@ public class TheFindContextFromUrlMethod
1213
[TestCase("https://github.com/github/VisualStudio/blob/master/README.md", "github")]
1314
public void Owner(string url, string expectOwner)
1415
{
15-
var target = new GitHubContextService();
16+
var target = CreateGitHubContextService();
1617

1718
var context = target.FindContextFromUrl(url);
1819

@@ -25,7 +26,7 @@ public void Owner(string url, string expectOwner)
2526
[TestCase("https://github.com/github/VisualStudio/blob/master/README.md", "VisualStudio")]
2627
public void RepositoryName(string url, string expectRepositoryName)
2728
{
28-
var target = new GitHubContextService();
29+
var target = CreateGitHubContextService();
2930

3031
var context = target.FindContextFromUrl(url);
3132

@@ -38,7 +39,7 @@ public void RepositoryName(string url, string expectRepositoryName)
3839
[TestCase("https://github.com/github/VisualStudio/blob/master/README.md", "github.com")]
3940
public void Host(string url, string expectHost)
4041
{
41-
var target = new GitHubContextService();
42+
var target = CreateGitHubContextService();
4243

4344
var context = target.FindContextFromUrl(url);
4445

@@ -55,7 +56,7 @@ public void Host(string url, string expectHost)
5556
[TestCase("https://github.com/github/VisualStudio/pull/NaN", null)]
5657
public void PullRequest(string url, int? expectPullRequest)
5758
{
58-
var target = new GitHubContextService();
59+
var target = CreateGitHubContextService();
5960

6061
var context = target.FindContextFromUrl(url);
6162

@@ -70,7 +71,7 @@ public void PullRequest(string url, int? expectPullRequest)
7071
[TestCase("https://github.com/github/VisualStudio/blob/0d264d50c57d701fa62d202f481075a6c6dbdce8/src/Code.cs#L86", "src/Code.cs")]
7172
public void Path(string url, string expectPath)
7273
{
73-
var target = new GitHubContextService();
74+
var target = CreateGitHubContextService();
7475

7576
var context = target.FindContextFromUrl(url);
7677

@@ -81,7 +82,7 @@ public void Path(string url, string expectPath)
8182
[TestCase("https://github.com/github/VisualStudio/blob/fixes/branch/buggy.cs", "branch/buggy.cs")]
8283
public void ProblemPath(string url, string expectPath)
8384
{
84-
var target = new GitHubContextService();
85+
var target = CreateGitHubContextService();
8586

8687
var context = target.FindContextFromUrl(url);
8788

@@ -97,7 +98,7 @@ public void ProblemPath(string url, string expectPath)
9798
[TestCase("https://github.com/github/VisualStudio/blob/0d264d50c57d701fa62d202f481075a6c6dbdce8/src/Code.cs#L86", 86)]
9899
public void Line(string url, int? expectLine)
99100
{
100-
var target = new GitHubContextService();
101+
var target = CreateGitHubContextService();
101102

102103
var context = target.FindContextFromUrl(url);
103104

@@ -109,7 +110,7 @@ public void Line(string url, int? expectLine)
109110
[TestCase("https://github.com/github/VisualStudio/blob/master/Code.cs#L115-L116", 115, 116)]
110111
public void LineEnd(string url, int? expectLine, int? expectLineEnd)
111112
{
112-
var target = new GitHubContextService();
113+
var target = CreateGitHubContextService();
113114

114115
var context = target.FindContextFromUrl(url);
115116

@@ -122,7 +123,7 @@ public void LineEnd(string url, int? expectLine, int? expectLineEnd)
122123
[TestCase("https://github.com/github/VisualStudio", false)]
123124
public void IsNull(string url, bool expectNull)
124125
{
125-
var target = new GitHubContextService();
126+
var target = CreateGitHubContextService();
126127

127128
var context = target.FindContextFromUrl(url);
128129

@@ -136,7 +137,7 @@ public class TheToMethod
136137
public void DefaultGitHubDotCom()
137138
{
138139
var context = new GitHubContext { Host = "github.com", Owner = "github", RepositoryName = "VisualStudio" };
139-
var target = new GitHubContextService();
140+
var target = CreateGitHubContextService();
140141

141142
var uri = target.ToRepositoryUrl(context);
142143

@@ -155,7 +156,7 @@ public class TheFindContextFromWindowTitleMethod
155156
[TestCase("github/$: Description - Google Chrome", null, Description = "Must contain only letters, numbers, `_`, `.` or `-`")]
156157
public void RepositoryName(string windowTitle, string expectRepositoryName)
157158
{
158-
var target = new GitHubContextService();
159+
var target = CreateGitHubContextService();
159160

160161
var context = target.FindContextFromWindowTitle(windowTitle);
161162

@@ -171,7 +172,7 @@ public void RepositoryName(string windowTitle, string expectRepositoryName)
171172
[TestCase("-/Repository: Description - Google Chrome", null, Description = "Must start with letter or number")]
172173
public void Owner(string windowTitle, string expectOwner)
173174
{
174-
var target = new GitHubContextService();
175+
var target = CreateGitHubContextService();
175176

176177
var context = target.FindContextFromWindowTitle(windowTitle);
177178

@@ -217,7 +218,7 @@ public void Owner(string windowTitle, string expectOwner)
217218
public void Branch(string branch, string expectBranch)
218219
{
219220
var windowTitle = $"VisualStudio/src/GitHub.VisualStudio/Resources/icons at {branch} · github/VisualStudio - Google Chrome";
220-
var target = new GitHubContextService();
221+
var target = CreateGitHubContextService();
221222

222223
var context = target.FindContextFromWindowTitle(windowTitle);
223224

@@ -234,7 +235,7 @@ public void Branch(string branch, string expectBranch)
234235
[TestCase("VisualStudio/GitHub.Exports.csproj at 89484dc25a3a475d3253afdc3bd3ddd6c6999c3b · github/VisualStudio - Google Chrome", "github", "VisualStudio", "89484dc25a3a475d3253afdc3bd3ddd6c6999c3b")]
235236
public void OwnerRepositoryBranch(string windowTitle, string expectOwner, string expectRepositoryName, string expectBranch)
236237
{
237-
var target = new GitHubContextService();
238+
var target = CreateGitHubContextService();
238239

239240
var context = target.FindContextFromWindowTitle(windowTitle);
240241

@@ -247,7 +248,7 @@ public void OwnerRepositoryBranch(string windowTitle, string expectOwner, string
247248
[TestCase("GitHub - github/VisualStudio at refactor/pr-list - Mozilla Firefox", "github", "VisualStudio", "refactor/pr-list", Description = "Firefox")]
248249
public void TreeBranch(string windowTitle, string expectOwner, string expectRepositoryName, string expectBranch)
249250
{
250-
var target = new GitHubContextService();
251+
var target = CreateGitHubContextService();
251252

252253
var context = target.FindContextFromWindowTitle(windowTitle);
253254

@@ -260,7 +261,7 @@ public void TreeBranch(string windowTitle, string expectOwner, string expectRepo
260261
[TestCase("Branches · github/VisualStudio · GitHub - Mozilla Firefox", "github", "VisualStudio", Description = "Firefox")]
261262
public void Branches(string windowTitle, string expectOwner, string expectRepositoryName)
262263
{
263-
var target = new GitHubContextService();
264+
var target = CreateGitHubContextService();
264265

265266
var context = target.FindContextFromWindowTitle(windowTitle);
266267

@@ -272,7 +273,7 @@ public void Branches(string windowTitle, string expectOwner, string expectReposi
272273
[TestCase("Description · Pull Request #1763 · github/VisualStudio · GitHub - Mozilla Firefox", 1763, Description = "Firefox")]
273274
public void PullRequest(string windowTitle, int expectPullRequest)
274275
{
275-
var target = new GitHubContextService();
276+
var target = CreateGitHubContextService();
276277

277278
var context = target.FindContextFromWindowTitle(windowTitle);
278279

@@ -283,7 +284,7 @@ public void PullRequest(string windowTitle, int expectPullRequest)
283284
[TestCase("Scrape browser titles · Issue #4 · jcansdale/VisualStudio · GitHub - Mozilla Firefox", 4, Description = "Firefox")]
284285
public void Issue(string windowTitle, int expectIssue)
285286
{
286-
var target = new GitHubContextService();
287+
var target = CreateGitHubContextService();
287288

288289
var context = target.FindContextFromWindowTitle(windowTitle);
289290

@@ -295,7 +296,7 @@ public void Issue(string windowTitle, int expectIssue)
295296
[TestCase("VisualStudio/README.md at master · jcansdale/VisualStudio · GitHub - Mozilla Firefox", "README.md", Description = "Firefox")]
296297
public void Path(string windowTitle, string expectPath)
297298
{
298-
var target = new GitHubContextService();
299+
var target = CreateGitHubContextService();
299300

300301
var context = target.FindContextFromWindowTitle(windowTitle);
301302

@@ -308,12 +309,18 @@ public void Path(string windowTitle, string expectPath)
308309
[TestCase("GitHub - jcansdale/GhostAssemblies - Mozilla Firefox", "jcansdale", "GhostAssemblies", Description = "No description, Firefox")]
309310
public void RepositoryHome(string windowTitle, string expectOwner, string expectRepositoryName)
310311
{
311-
var target = new GitHubContextService();
312+
var target = CreateGitHubContextService();
312313

313314
var context = target.FindContextFromWindowTitle(windowTitle);
314315

315316
Assert.That(context?.Owner, Is.EqualTo(expectOwner));
316317
Assert.That(context?.RepositoryName, Is.EqualTo(expectRepositoryName));
317318
}
318319
}
320+
321+
static GitHubContextService CreateGitHubContextService()
322+
{
323+
var sp = Substitute.For<IServiceProvider>();
324+
return new GitHubContextService(sp);
325+
}
319326
}

0 commit comments

Comments
 (0)