PageRenderTime 102ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/main/tests/UnitTests/MonoDevelop.CSharpBinding/AutomaticBracketInsertionTests.cs

http://github.com/mono/monodevelop
C# | 488 lines | 408 code | 55 blank | 25 comment | 4 complexity | 9aa5b9966241c13f845eca9004039dca MD5 | raw file
Possible License(s): LGPL-2.0, GPL-2.0, CC-BY-SA-3.0, MIT, LGPL-2.1, Apache-2.0, BSD-3-Clause
  1. //
  2. // AutomaticBracketInsertionTests.cs
  3. //
  4. // Author:
  5. // Mike Krüger <mkrueger@xamarin.com>
  6. //
  7. // Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining a copy
  10. // of this software and associated documentation files (the "Software"), to deal
  11. // in the Software without restriction, including without limitation the rights
  12. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. // copies of the Software, and to permit persons to whom the Software is
  14. // furnished to do so, subject to the following conditions:
  15. //
  16. // The above copyright notice and this permission notice shall be included in
  17. // all copies or substantial portions of the Software.
  18. //
  19. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. // THE SOFTWARE.
  26. using System;
  27. using NUnit.Framework;
  28. using System.Linq;
  29. using UnitTests;
  30. using MonoDevelop.CSharpBinding.Tests;
  31. using MonoDevelop.Ide.Gui;
  32. using MonoDevelop.CSharp.Completion;
  33. using MonoDevelop.Ide.CodeCompletion;
  34. using MonoDevelop.Ide.Editor;
  35. using MonoDevelop.Ide.Editor.Extension;
  36. using Microsoft.CodeAnalysis;
  37. using MonoDevelop.Projects;
  38. using MonoDevelop.Core.ProgressMonitoring;
  39. using MonoDevelop.Ide.TypeSystem;
  40. using MonoDevelop.CSharp.Formatting;
  41. using MonoDevelop.Projects.Policies;
  42. using MonoDevelop.Core;
  43. using System.Threading.Tasks;
  44. namespace MonoDevelop.CSharpBinding
  45. {
  46. [TestFixture]
  47. public class AutomaticBracketInsertionTests : TestBase
  48. {
  49. class TestCompletionWidget : ICompletionWidget
  50. {
  51. MonoDevelop.Ide.Editor.TextEditor editor;
  52. DocumentContext documentContext;
  53. public TestCompletionWidget (TextEditor editor, DocumentContext document)
  54. {
  55. this.editor = editor;
  56. documentContext = document;
  57. }
  58. public string CompletedWord {
  59. get;
  60. set;
  61. }
  62. #region ICompletionWidget implementation
  63. public event EventHandler CompletionContextChanged {
  64. add { /* TODO */ }
  65. remove { /* TODO */ }
  66. }
  67. public string GetText (int startOffset, int endOffset)
  68. {
  69. return editor.GetTextBetween (startOffset, endOffset);
  70. }
  71. public char GetChar (int offset)
  72. {
  73. return editor.GetCharAt (offset);
  74. }
  75. public CodeCompletionContext CreateCodeCompletionContext (int triggerOffset)
  76. {
  77. var line = editor.GetLineByOffset (triggerOffset);
  78. return new CodeCompletionContext {
  79. TriggerOffset = triggerOffset,
  80. TriggerLine = line.LineNumber,
  81. TriggerLineOffset = line.Offset,
  82. TriggerXCoord = 0,
  83. TriggerYCoord = 0,
  84. TriggerTextHeight = 0,
  85. TriggerWordLength = 0
  86. };
  87. }
  88. public CodeCompletionContext CurrentCodeCompletionContext {
  89. get {
  90. return CreateCodeCompletionContext (editor.CaretOffset);
  91. }
  92. }
  93. public string GetCompletionText (CodeCompletionContext ctx)
  94. {
  95. return "";
  96. }
  97. public void SetCompletionText (CodeCompletionContext ctx, string partial_word, string complete_word)
  98. {
  99. this.CompletedWord = complete_word;
  100. }
  101. public void SetCompletionText (CodeCompletionContext ctx, string partial_word, string complete_word, int offset)
  102. {
  103. this.CompletedWord = complete_word;
  104. }
  105. public void Replace (int offset, int count, string text)
  106. {
  107. }
  108. public int CaretOffset {
  109. get {
  110. return editor.CaretOffset;
  111. }
  112. set {
  113. editor.CaretOffset = value;
  114. }
  115. }
  116. public int TextLength {
  117. get {
  118. return editor.Length;
  119. }
  120. }
  121. public int SelectedLength {
  122. get {
  123. return 0;
  124. }
  125. }
  126. public Gtk.Style GtkStyle {
  127. get {
  128. return null;
  129. }
  130. }
  131. double ICompletionWidget.ZoomLevel {
  132. get {
  133. return 1;
  134. }
  135. }
  136. #endregion
  137. }
  138. static async Task<Tuple<CSharpCompletionTextEditorExtension,TestViewContent>> Setup (string input)
  139. {
  140. TestWorkbenchWindow tww = new TestWorkbenchWindow ();
  141. TestViewContent content = new TestViewContent ();
  142. tww.ViewContent = content;
  143. content.ContentName = "/a.cs";
  144. content.Data.MimeType = "text/x-csharp";
  145. var doc = new MonoDevelop.Ide.Gui.Document (tww);
  146. var text = input;
  147. int endPos = text.IndexOf ('$');
  148. if (endPos >= 0)
  149. text = text.Substring (0, endPos) + text.Substring (endPos + 1);
  150. content.Text = text;
  151. content.CursorPosition = System.Math.Max (0, endPos);
  152. var project = Services.ProjectService.CreateProject ("C#");
  153. project.Name = "test";
  154. project.FileName = "test.csproj";
  155. project.Files.Add (new ProjectFile (content.ContentName, BuildAction.Compile));
  156. project.Policies.Set (PolicyService.InvariantPolicies.Get<CSharpFormattingPolicy> (), CSharpFormatter.MimeType);
  157. var solution = new MonoDevelop.Projects.Solution ();
  158. solution.AddConfiguration ("", true);
  159. solution.DefaultSolutionFolder.AddItem (project);
  160. using (var monitor = new ProgressMonitor ())
  161. await TypeSystemService.Load (solution, monitor);
  162. content.Project = project;
  163. doc.SetProject (project);
  164. var compExt = new CSharpCompletionTextEditorExtension ();
  165. compExt.Initialize (doc.Editor, doc);
  166. content.Contents.Add (compExt);
  167. await doc.UpdateParseDocument ();
  168. TypeSystemService.Unload (solution);
  169. return Tuple.Create (compExt, content);
  170. }
  171. async Task<string> Test(string input, string type, string member, Gdk.Key key = Gdk.Key.Return, bool isDelegateExpected = false)
  172. {
  173. var s = await Setup (input);
  174. var ext = s.Item1;
  175. TestViewContent content = s.Item2;
  176. var listWindow = new CompletionListWindow ();
  177. var widget = new TestCompletionWidget (ext.Editor, ext.DocumentContext);
  178. listWindow.CompletionWidget = widget;
  179. listWindow.CodeCompletionContext = widget.CurrentCodeCompletionContext;
  180. var model = ext.DocumentContext.ParsedDocument.GetAst<SemanticModel> ();
  181. Ide.IdeApp.Preferences.AddParenthesesAfterCompletion.Set (true);
  182. Ide.IdeApp.Preferences.AddOpeningOnly.Set (false);
  183. var t = model.Compilation.GetTypeByMetadataName (type);
  184. var method = member != null ? t.GetMembers().First (m => m.Name == member) : t.GetMembers ().OfType<IMethodSymbol> ().First (m => m.MethodKind == MethodKind.Constructor);
  185. var factory = new RoslynCodeCompletionFactory (ext, model);
  186. var data = new RoslynSymbolCompletionData (null, factory, method);
  187. data.IsDelegateExpected = isDelegateExpected;
  188. KeyActions ka = KeyActions.Process;
  189. data.InsertCompletionText (listWindow, ref ka, KeyDescriptor.FromGtk (key, (char)key, Gdk.ModifierType.None));
  190. return widget.CompletedWord;
  191. }
  192. [Test]
  193. public async Task TestSimpleCase ()
  194. {
  195. string completion = await Test (@"class MyClass
  196. {
  197. void FooBar ()
  198. {
  199. $
  200. }
  201. }", "MyClass", "FooBar");
  202. Assert.AreEqual ("FooBar();|", completion);
  203. }
  204. [Test]
  205. public async Task TestBracketAlreadyThere ()
  206. {
  207. string completion = await Test (@"class MyClass
  208. {
  209. void FooBar ()
  210. {
  211. $ ();
  212. }
  213. }", "MyClass", "FooBar");
  214. Assert.AreEqual ("FooBar", completion);
  215. }
  216. [Test]
  217. public async Task TestBracketAlreadyThereCase2 ()
  218. {
  219. string completion = await Test (@"class MyClass
  220. {
  221. void FooBar ()
  222. {
  223. Test($);
  224. }
  225. }", "MyClass", "FooBar");
  226. Assert.AreEqual ("FooBar()|", completion);
  227. }
  228. [Test]
  229. public async Task TestParameter ()
  230. {
  231. string completion = await Test (@"class MyClass
  232. {
  233. void FooBar ()
  234. {
  235. Test(foo, $
  236. }
  237. }", "MyClass", "FooBar");
  238. Assert.AreEqual ("FooBar()|", completion);
  239. }
  240. [Test]
  241. public async Task TestOverloads ()
  242. {
  243. string completion = await Test (@"class MyClass
  244. {
  245. void FooBar (int foo)
  246. {
  247. }
  248. void FooBar ()
  249. {
  250. $
  251. }
  252. }", "MyClass", "FooBar");
  253. Assert.AreEqual ("FooBar(|);", completion);
  254. }
  255. [Test]
  256. public async Task TestExpressionCase ()
  257. {
  258. string completion = await Test (@"class MyClass
  259. {
  260. int FooBar ()
  261. {
  262. int i;
  263. i = $
  264. }
  265. }", "MyClass", "FooBar");
  266. Assert.AreEqual ("FooBar()|", completion);
  267. }
  268. [Test]
  269. public async Task TestExpressionCaseWithOverloads ()
  270. {
  271. string completion = await Test (@"class MyClass
  272. {
  273. int FooBar (int foo)
  274. {
  275. }
  276. int FooBar ()
  277. {
  278. int i;
  279. i = $
  280. }
  281. }", "MyClass", "FooBar");
  282. Assert.AreEqual ("FooBar(|)", completion);
  283. }
  284. [Test]
  285. public async Task TestDelegateCase ()
  286. {
  287. string completion = await Test (@"using System;
  288. class MyClass
  289. {
  290. int FooBar ()
  291. {
  292. Func<int> i;
  293. i = $
  294. }
  295. }", "MyClass", "FooBar", Gdk.Key.Return, true);
  296. Assert.AreEqual ("FooBar", completion);
  297. }
  298. [Test]
  299. public async Task TestDotCompletion ()
  300. {
  301. string completion = await Test (@"class MyClass
  302. {
  303. void FooBar ()
  304. {
  305. $
  306. }
  307. }", "MyClass", "FooBar", (Gdk.Key)'.');
  308. Assert.AreEqual ("FooBar()", completion);
  309. }
  310. [Test]
  311. public async Task TestConstructorSimple ()
  312. {
  313. string completion = await Test (@"class MyClass
  314. {
  315. public MyClass () {}
  316. void FooBar ()
  317. {
  318. $
  319. }
  320. }", "MyClass", null);
  321. Assert.AreEqual ("MyClass()|", completion);
  322. }
  323. [Test]
  324. public async Task TestConstructorWithOverloads ()
  325. {
  326. string completion = await Test (@"class MyClass
  327. {
  328. public MyClass () {}
  329. public MyClass (int x) {}
  330. void FooBar ()
  331. {
  332. $
  333. }
  334. }", "MyClass", null);
  335. Assert.AreEqual ("MyClass(|)", completion);
  336. }
  337. [Test]
  338. public async Task TestGenericCase1 ()
  339. {
  340. string completion = await Test (@"class MyClass
  341. {
  342. void FooBar<T> ()
  343. {
  344. $
  345. }
  346. }", "MyClass", "FooBar");
  347. Assert.AreEqual ("FooBar<|>();", completion);
  348. }
  349. [Test]
  350. public async Task TestGenericCase2 ()
  351. {
  352. string completion = await Test (@"class MyClass
  353. {
  354. void FooBar<T> (T t)
  355. {
  356. $
  357. }
  358. }", "MyClass", "FooBar");
  359. Assert.AreEqual ("FooBar(|);", completion);
  360. }
  361. [Test]
  362. public async Task TestGenericDotCompletion ()
  363. {
  364. string completion = await Test (@"class MyClass
  365. {
  366. void FooBar<T> ()
  367. {
  368. $
  369. }
  370. }", "MyClass", "FooBar", (Gdk.Key)'.');
  371. Assert.AreEqual ("FooBar<>()", completion);
  372. }
  373. [Test]
  374. public async Task TestInsertionBug ()
  375. {
  376. string completion = await Test (@"class MyClass
  377. {
  378. void FooBar ()
  379. {
  380. $
  381. if (true) { }
  382. }
  383. }", "MyClass", "FooBar");
  384. Assert.AreEqual ("FooBar();|", completion);
  385. }
  386. [Test]
  387. public async Task TestGenericConstructor ()
  388. {
  389. string completion = await Test (@"class MyClass<T>
  390. {
  391. public MyClass () {}
  392. void FooBar ()
  393. {
  394. $
  395. }
  396. }", "MyClass`1", null);
  397. Assert.AreEqual ("MyClass<|>()", completion);
  398. }
  399. [Test]
  400. public async Task TestBracketAlreadyThereGenericCase ()
  401. {
  402. string completion = await Test (@"class MyClass
  403. {
  404. void FooBar<T> ()
  405. {
  406. $<string>();
  407. }
  408. }", "MyClass", "FooBar");
  409. Assert.AreEqual ("FooBar", completion);
  410. }
  411. [Test]
  412. public async Task TestBug41308 ()
  413. {
  414. string completion = await Test (@"
  415. class MyClass
  416. {
  417. void Test<T> (T t)
  418. {
  419. }
  420. void FooBar ()
  421. {
  422. $
  423. }
  424. }", "MyClass", "Test");
  425. Assert.AreEqual ("Test(|);", completion);
  426. }
  427. }
  428. }