|
29 | 29 | using System.Linq; |
30 | 30 | using System.Threading.Tasks; |
31 | 31 | using MonoDevelop.Core; |
| 32 | +using MonoDevelop.Ide.Gui.Documents; |
32 | 33 | using MonoDevelop.Projects; |
33 | 34 | using NUnit.Framework; |
34 | 35 | using UnitTests; |
@@ -368,12 +369,125 @@ public async Task AdditionalFiles_EditorConfigFiles () |
368 | 369 |
|
369 | 370 | Assert.IsTrue (additionalDocs.Any (d => d.FilePath == expectedAdditionalFileName)); |
370 | 371 | Assert.IsTrue (editorConfigDocs.Any (d => d.FilePath == expectedEditorConfigFileName)); |
| 372 | + |
371 | 373 | } finally { |
372 | 374 | TypeSystemServiceTestExtensions.UnloadSolution (sol); |
373 | 375 | } |
374 | 376 | } |
375 | 377 | } |
376 | 378 |
|
| 379 | + [Test] |
| 380 | + public async Task EditorConfigFile_ModifiedExternally () |
| 381 | + { |
| 382 | + FilePath solFile = Util.GetSampleProject ("additional-files", "additional-files.sln"); |
| 383 | + |
| 384 | + using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile)) |
| 385 | + using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) { |
| 386 | + try { |
| 387 | + var project = sol.GetAllProjects ().Single (); |
| 388 | + |
| 389 | + FilePath editorConfigFileName = solFile.ParentDirectory.Combine (".editorconfig"); |
| 390 | + var projectInfo = ws.CurrentSolution.Projects.Single (); |
| 391 | + var editorConfigDoc = projectInfo.AnalyzerConfigDocuments.Single (d => d.FilePath == editorConfigFileName); |
| 392 | + |
| 393 | + bool analyzerConfigDocumentChanged = false; |
| 394 | + ws.WorkspaceChanged += (sender, e) => { |
| 395 | + if (e.DocumentId == editorConfigDoc.Id && |
| 396 | + e.Kind == Microsoft.CodeAnalysis.WorkspaceChangeKind.AnalyzerConfigDocumentChanged) { |
| 397 | + analyzerConfigDocumentChanged = true; |
| 398 | + } |
| 399 | + }; |
| 400 | + |
| 401 | + // Add error style to .editorconfig |
| 402 | + string contents = |
| 403 | + "root = true\r\n" + |
| 404 | + "\r\n" + |
| 405 | + "[*.cs]\r\n" + |
| 406 | + "csharp_style_var_for_built_in_types = true:error\r\n"; |
| 407 | + File.WriteAllText (editorConfigFileName, contents); |
| 408 | + FileService.NotifyFileChanged (editorConfigFileName); |
| 409 | + |
| 410 | + Func<bool> action = () => analyzerConfigDocumentChanged; |
| 411 | + await AssertIsTrueWithTimeout (action, "Timed out waiting for analyzer config file changed event", 10000); |
| 412 | + |
| 413 | + } finally { |
| 414 | + TypeSystemServiceTestExtensions.UnloadSolution (sol); |
| 415 | + } |
| 416 | + } |
| 417 | + } |
| 418 | + |
| 419 | + [Test] |
| 420 | + public async Task EditorConfigFile_ModifiedInTextEditor () |
| 421 | + { |
| 422 | + FilePath solFile = Util.GetSampleProject ("additional-files", "additional-files.sln"); |
| 423 | + |
| 424 | + using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile)) |
| 425 | + using (var ws = await TypeSystemServiceTestExtensions.LoadSolution (sol)) { |
| 426 | + try { |
| 427 | + var project = sol.GetAllProjects ().Single (); |
| 428 | + |
| 429 | + FilePath editorConfigFileName = solFile.ParentDirectory.Combine (".editorconfig"); |
| 430 | + var textFileModel = new TextBufferFileModel (); |
| 431 | + var mimeType = MimeTypeCatalog.Instance.FindMimeTypeForFile (editorConfigFileName); |
| 432 | + textFileModel.CreateNew (editorConfigFileName, mimeType?.Id); |
| 433 | + |
| 434 | + var projectInfo = ws.CurrentSolution.Projects.Single (); |
| 435 | + Microsoft.CodeAnalysis.AnalyzerConfigDocument editorConfigDoc = |
| 436 | + projectInfo.AnalyzerConfigDocuments.Single (d => d.FilePath == editorConfigFileName); |
| 437 | + |
| 438 | + int analyzerConfigDocumentChangedCount = 0; |
| 439 | + ws.WorkspaceChanged += (sender, e) => { |
| 440 | + if (e.DocumentId == editorConfigDoc.Id && |
| 441 | + e.Kind == Microsoft.CodeAnalysis.WorkspaceChangeKind.AnalyzerConfigDocumentChanged) { |
| 442 | + analyzerConfigDocumentChangedCount++; |
| 443 | + } |
| 444 | + }; |
| 445 | + |
| 446 | + using (var fileRegistration = IdeApp.TypeSystemService.RegisterOpenDocument ( |
| 447 | + null, // No owner. |
| 448 | + editorConfigFileName, |
| 449 | + textFileModel.TextBuffer)) { |
| 450 | + |
| 451 | + Assert.IsTrue (ws.IsDocumentOpen (editorConfigDoc.Id)); |
| 452 | + |
| 453 | + Func<bool> action = () => analyzerConfigDocumentChangedCount == 1; |
| 454 | + await AssertIsTrueWithTimeout (action, "Timed out waiting for analyzer config file changed event on opening file", 100000); |
| 455 | + |
| 456 | + // Add error style to .editorconfig |
| 457 | + string contents = |
| 458 | + "root = true\r\n" + |
| 459 | + "\r\n" + |
| 460 | + "[*.cs]\r\n" + |
| 461 | + "csharp_style_var_for_built_in_types = true:error\r\n"; |
| 462 | + textFileModel.SetText (contents); |
| 463 | + await textFileModel.Save (); |
| 464 | + |
| 465 | + action = () => analyzerConfigDocumentChangedCount == 2; |
| 466 | + await AssertIsTrueWithTimeout (action, "Timed out waiting for analyzer config file changed event", 100000); |
| 467 | + } |
| 468 | + // After the file registration is disposed the document should be closed. |
| 469 | + Assert.IsFalse (ws.IsDocumentOpen (editorConfigDoc.Id)); |
| 470 | + } finally { |
| 471 | + TypeSystemServiceTestExtensions.UnloadSolution (sol); |
| 472 | + } |
| 473 | + } |
| 474 | + } |
| 475 | + |
| 476 | + async Task AssertIsTrueWithTimeout (Func<bool> action, string message, int timeout) |
| 477 | + { |
| 478 | + int howLong = 0; |
| 479 | + const int interval = 200; // ms |
| 480 | + |
| 481 | + while (!action ()) { |
| 482 | + if (howLong >= timeout) { |
| 483 | + Assert.Fail (message); |
| 484 | + } |
| 485 | + |
| 486 | + await Task.Delay (interval); |
| 487 | + howLong += interval; |
| 488 | + } |
| 489 | + } |
| 490 | + |
377 | 491 | /// <summary> |
378 | 492 | /// Clear all other package sources and just use the main NuGet package source when |
379 | 493 | /// restoring the packages for the project tests. |
|
0 commit comments