PageRenderTime 52ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/src/EditorFeatures/Test/CallHierarchy/CallHierarchyTestState.cs

https://gitlab.com/sharadag/Roslyn
C# | 288 lines | 240 code | 47 blank | 1 comment | 14 complexity | d252bbe4769708c0c829b418869f2303 MD5 | raw file
  1. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Collections.Immutable;
  5. using System.ComponentModel.Composition.Hosting;
  6. using System.Linq;
  7. using System.Threading.Tasks;
  8. using System.Xml.Linq;
  9. using Microsoft.CodeAnalysis.Editor.Commands;
  10. using Microsoft.CodeAnalysis.Editor.CSharp.CallHierarchy;
  11. using Microsoft.CodeAnalysis.Editor.Host;
  12. using Microsoft.CodeAnalysis.Editor.Implementation.CallHierarchy;
  13. using Microsoft.CodeAnalysis.Editor.Implementation.Notification;
  14. using Microsoft.CodeAnalysis.Editor.SymbolMapping;
  15. using Microsoft.CodeAnalysis.Editor.UnitTests.Utilities;
  16. using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
  17. using Microsoft.CodeAnalysis.Notification;
  18. using Microsoft.VisualStudio.Language.CallHierarchy;
  19. using Microsoft.VisualStudio.Text;
  20. using Microsoft.VisualStudio.Text.Editor;
  21. using Roslyn.Utilities;
  22. using Xunit;
  23. namespace Microsoft.CodeAnalysis.Editor.UnitTests.CallHierarchy
  24. {
  25. public class CallHierarchyTestState
  26. {
  27. private readonly CallHierarchyCommandHandler _commandHandler;
  28. private readonly MockCallHierarchyPresenter _presenter;
  29. internal TestWorkspace Workspace;
  30. private readonly ITextBuffer _subjectBuffer;
  31. private readonly IWpfTextView _textView;
  32. private class MockCallHierarchyPresenter : ICallHierarchyPresenter
  33. {
  34. public CallHierarchyItem PresentedRoot;
  35. public void PresentRoot(CallHierarchyItem root)
  36. {
  37. this.PresentedRoot = root;
  38. }
  39. }
  40. private class MockSearchCallback : ICallHierarchySearchCallback
  41. {
  42. private readonly Action<CallHierarchyItem> _verifyMemberItem;
  43. private readonly TaskCompletionSource<object> _completionSource = new TaskCompletionSource<object>();
  44. private readonly Action<ICallHierarchyNameItem> _verifyNameItem;
  45. public MockSearchCallback(Action<CallHierarchyItem> verify)
  46. {
  47. _verifyMemberItem = verify;
  48. }
  49. public MockSearchCallback(Action<ICallHierarchyNameItem> verify)
  50. {
  51. _verifyNameItem = verify;
  52. }
  53. public void AddResult(ICallHierarchyNameItem item)
  54. {
  55. _verifyNameItem(item);
  56. }
  57. public void AddResult(ICallHierarchyMemberItem item)
  58. {
  59. _verifyMemberItem((CallHierarchyItem)item);
  60. }
  61. public void InvalidateResults()
  62. {
  63. }
  64. public void ReportProgress(int current, int maximum)
  65. {
  66. }
  67. public void SearchFailed(string message)
  68. {
  69. _completionSource.SetException(new Exception(message));
  70. }
  71. public void SearchSucceeded()
  72. {
  73. _completionSource.SetResult(null);
  74. }
  75. internal void WaitForCompletion()
  76. {
  77. _completionSource.Task.Wait();
  78. }
  79. }
  80. public static async Task<CallHierarchyTestState> CreateAsync(XElement markup, params Type[] additionalTypes)
  81. {
  82. var exportProvider = CreateExportProvider(additionalTypes);
  83. var workspace = await TestWorkspace.CreateAsync(markup, exportProvider: exportProvider);
  84. return new CallHierarchyTestState(workspace);
  85. }
  86. private CallHierarchyTestState(TestWorkspace workspace)
  87. {
  88. this.Workspace = workspace;
  89. var testDocument = Workspace.Documents.Single(d => d.CursorPosition.HasValue);
  90. _textView = testDocument.GetTextView();
  91. _subjectBuffer = testDocument.GetTextBuffer();
  92. var provider = Workspace.GetService<CallHierarchyProvider>();
  93. var notificationService = Workspace.Services.GetService<INotificationService>() as INotificationServiceCallback;
  94. var callback = new Action<string, string, NotificationSeverity>((message, title, severity) => NotificationMessage = message);
  95. notificationService.NotificationCallback = callback;
  96. _presenter = new MockCallHierarchyPresenter();
  97. _commandHandler = new CallHierarchyCommandHandler(new[] { _presenter }, provider, TestWaitIndicator.Default);
  98. }
  99. private static VisualStudio.Composition.ExportProvider CreateExportProvider(Type[] additionalTypes)
  100. {
  101. var catalog = TestExportProvider.MinimumCatalogWithCSharpAndVisualBasic
  102. .WithPart(typeof(CallHierarchyProvider))
  103. .WithPart(typeof(SymbolMappingServiceFactory))
  104. .WithPart(typeof(EditorNotificationServiceFactory))
  105. .WithParts(additionalTypes);
  106. return MinimalTestExportProvider.CreateExportProvider(catalog);
  107. }
  108. public static async Task<CallHierarchyTestState> CreateAsync(string markup, params Type[] additionalTypes)
  109. {
  110. var exportProvider = CreateExportProvider(additionalTypes);
  111. var workspace = await TestWorkspace.CreateCSharpAsync(markup, exportProvider: exportProvider);
  112. return new CallHierarchyTestState(markup, workspace);
  113. }
  114. private CallHierarchyTestState(string markup, TestWorkspace workspace)
  115. {
  116. this.Workspace = workspace;
  117. var testDocument = Workspace.Documents.Single(d => d.CursorPosition.HasValue);
  118. _textView = testDocument.GetTextView();
  119. _subjectBuffer = testDocument.GetTextBuffer();
  120. var provider = Workspace.GetService<CallHierarchyProvider>();
  121. var notificationService = Workspace.Services.GetService<INotificationService>() as INotificationServiceCallback;
  122. var callback = new Action<string, string, NotificationSeverity>((message, title, severity) => NotificationMessage = message);
  123. notificationService.NotificationCallback = callback;
  124. _presenter = new MockCallHierarchyPresenter();
  125. _commandHandler = new CallHierarchyCommandHandler(new[] { _presenter }, provider, TestWaitIndicator.Default);
  126. }
  127. internal string NotificationMessage
  128. {
  129. get;
  130. private set;
  131. }
  132. internal CallHierarchyItem GetRoot()
  133. {
  134. var args = new ViewCallHierarchyCommandArgs(_textView, _subjectBuffer);
  135. _commandHandler.ExecuteCommand(args, () => { });
  136. return _presenter.PresentedRoot;
  137. }
  138. internal IImmutableSet<Document> GetDocuments(string[] documentNames)
  139. {
  140. var selectedDocuments = new List<Document>();
  141. this.Workspace.CurrentSolution.Projects.Do(p => p.Documents.Where(d => documentNames.Contains(d.Name)).Do(d => selectedDocuments.Add(d)));
  142. return ImmutableHashSet.CreateRange<Document>(selectedDocuments);
  143. }
  144. internal void SearchRoot(CallHierarchyItem root, string displayName, Action<CallHierarchyItem> verify, CallHierarchySearchScope scope, IImmutableSet<Document> documents = null)
  145. {
  146. var callback = new MockSearchCallback(verify);
  147. var category = root.SupportedSearchCategories.First(c => c.DisplayName == displayName).Name;
  148. if (documents != null)
  149. {
  150. root.StartSearchWithDocuments(category, scope, callback, documents);
  151. }
  152. else
  153. {
  154. root.StartSearch(category, scope, callback);
  155. }
  156. callback.WaitForCompletion();
  157. }
  158. internal void SearchRoot(CallHierarchyItem root, string displayName, Action<ICallHierarchyNameItem> verify, CallHierarchySearchScope scope, IImmutableSet<Document> documents = null)
  159. {
  160. var callback = new MockSearchCallback(verify);
  161. var category = root.SupportedSearchCategories.First(c => c.DisplayName == displayName).Name;
  162. if (documents != null)
  163. {
  164. root.StartSearchWithDocuments(category, scope, callback, documents);
  165. }
  166. else
  167. {
  168. root.StartSearch(category, scope, callback);
  169. }
  170. callback.WaitForCompletion();
  171. }
  172. internal string ConvertToName(ICallHierarchyMemberItem root)
  173. {
  174. var name = root.MemberName;
  175. if (!string.IsNullOrEmpty(root.ContainingTypeName))
  176. {
  177. name = root.ContainingTypeName + "." + name;
  178. }
  179. if (!string.IsNullOrEmpty(root.ContainingNamespaceName))
  180. {
  181. name = root.ContainingNamespaceName + "." + name;
  182. }
  183. return name;
  184. }
  185. internal string ConvertToName(ICallHierarchyNameItem root)
  186. {
  187. return root.Name;
  188. }
  189. internal void VerifyRoot(CallHierarchyItem root, string name = "", string[] expectedCategories = null)
  190. {
  191. Assert.Equal(name, ConvertToName(root));
  192. if (expectedCategories != null)
  193. {
  194. var categories = root.SupportedSearchCategories.Select(s => s.DisplayName);
  195. foreach (var category in expectedCategories)
  196. {
  197. Assert.Contains(category, categories);
  198. }
  199. }
  200. }
  201. internal void VerifyResultName(CallHierarchyItem root, string searchCategory, string[] expectedCallers, CallHierarchySearchScope scope = CallHierarchySearchScope.EntireSolution, IImmutableSet<Document> documents = null)
  202. {
  203. this.SearchRoot(root, searchCategory, (ICallHierarchyNameItem c) =>
  204. {
  205. Assert.True(expectedCallers.Any());
  206. Assert.True(expectedCallers.Contains(ConvertToName(c)));
  207. },
  208. scope,
  209. documents);
  210. }
  211. internal void VerifyResult(CallHierarchyItem root, string searchCategory, string[] expectedCallers, CallHierarchySearchScope scope = CallHierarchySearchScope.EntireSolution, IImmutableSet<Document> documents = null)
  212. {
  213. this.SearchRoot(root, searchCategory, (CallHierarchyItem c) =>
  214. {
  215. Assert.True(expectedCallers.Any());
  216. Assert.True(expectedCallers.Contains(ConvertToName(c)));
  217. },
  218. scope,
  219. documents);
  220. }
  221. internal void Navigate(CallHierarchyItem root, string searchCategory, string callSite, CallHierarchySearchScope scope = CallHierarchySearchScope.EntireSolution, IImmutableSet<Document> documents = null)
  222. {
  223. CallHierarchyItem item = null;
  224. this.SearchRoot(root, searchCategory, (CallHierarchyItem c) => item = c,
  225. scope,
  226. documents);
  227. if (callSite == ConvertToName(item))
  228. {
  229. var detail = item.Details.FirstOrDefault();
  230. if (detail != null)
  231. {
  232. detail.NavigateTo();
  233. }
  234. else
  235. {
  236. item.NavigateTo();
  237. }
  238. }
  239. }
  240. }
  241. }