internal static IList<ITagSpan<IErrorTag>> GetErrorsFromUpdateSource(TestWorkspace workspace, TestHostDocument document, DiagnosticsUpdatedArgs updateArgs)
        {
            var source = new TestDiagnosticUpdateSource();

            var diagnosticWaiter = new DiagnosticServiceWaiter();
            var diagnosticListeners = SpecializedCollections.SingletonEnumerable(new Lazy<IAsynchronousOperationListener, FeatureMetadata>(
                () => diagnosticWaiter, new FeatureMetadata(new Dictionary<string, object>() { { "FeatureName", FeatureAttribute.DiagnosticService } })));

            var optionsService = workspace.Services.GetService<IOptionService>();
            var diagnosticService = new DiagnosticService(SpecializedCollections.SingletonEnumerable<IDiagnosticUpdateSource>(source), diagnosticListeners);

            var squiggleWaiter = new ErrorSquiggleWaiter();
            var foregroundService = new TestForegroundNotificationService();

            var buffer = document.GetTextBuffer();
            var taggerSource = new DiagnosticsSquiggleTaggerProvider.TagSource(buffer, foregroundService, diagnosticService, optionsService, squiggleWaiter);

            source.RaiseDiagnosticsUpdated(updateArgs);

            diagnosticWaiter.CreateWaitTask().PumpingWait();
            squiggleWaiter.CreateWaitTask().PumpingWait();

            var snapshot = buffer.CurrentSnapshot;
            var intervalTree = taggerSource.GetTagIntervalTreeForBuffer(buffer);
            var spans = intervalTree.GetIntersectingSpans(new SnapshotSpan(snapshot, 0, snapshot.Length));

            taggerSource.TestOnly_Dispose();

            return spans;
        }
Esempio n. 2
0
        public TestWorkspace GetWorkspace(
            string markup,
            ExportProvider exportProvider = null,
            string workspaceKind          = null
            )
        {
            // If it looks like XML, we'll treat it as XML; any parse error would be rejected and will throw.
            // We'll do a case insensitive search here so if somebody has a lowercase W it'll be tried (and
            // rejected by the XML parser) rather than treated as regular text.
            if (markup.TrimStart().StartsWith("<Workspace>", StringComparison.OrdinalIgnoreCase))
            {
                CloseTextView();
                _workspace?.Dispose();

                _workspace = TestWorkspace.CreateWorkspace(
                    XElement.Parse(markup),
                    exportProvider: exportProvider,
                    workspaceKind: workspaceKind
                    );
                _currentDocument = _workspace.Documents.First(d => d.CursorPosition.HasValue);
                Position         = _currentDocument.CursorPosition.Value;
                Code             = _currentDocument.GetTextBuffer().CurrentSnapshot.GetText();
                return(_workspace);
            }
            else
            {
                MarkupTestFile.GetPosition(markup.NormalizeLineEndings(), out Code, out Position);
                var workspace = GetWorkspace(exportProvider);
                _currentDocument = workspace.Documents.Single();
                return(workspace);
            }
        }
Esempio n. 3
0
            public override Task <TextAndVersion> LoadTextAndVersionAsync(Workspace workspace, DocumentId documentId, CancellationToken cancellationToken)
            {
                // Create a simple SourceText so that way we're not backing "closed" files by editors to best reflect
                // what closed files look like in reality.
                var text = SourceText.From(_hostDocument.GetTextBuffer().CurrentSnapshot.GetText());

                return(Task.FromResult(TextAndVersion.Create(text, VersionStamp.Create(), _hostDocument.FilePath)));
            }
        public RenameTrackingTestState(
            string markup,
            string languageName,
            bool onBeforeGlobalSymbolRenamedReturnValue = true,
            bool onAfterGlobalSymbolRenamedReturnValue = true)
        {
            this.Workspace = CreateTestWorkspace(markup, languageName, TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic());

            _hostDocument = Workspace.Documents.First();
            _view = _hostDocument.GetTextView();
            _view.Caret.MoveTo(new SnapshotPoint(_view.TextSnapshot, _hostDocument.CursorPosition.Value));
            _editorOperations = Workspace.GetService<IEditorOperationsFactoryService>().GetEditorOperations(_view);
            _historyRegistry = Workspace.ExportProvider.GetExport<ITextUndoHistoryRegistry>().Value;
            _mockRefactorNotifyService = new MockRefactorNotifyService
            {
                OnBeforeSymbolRenamedReturnValue = onBeforeGlobalSymbolRenamedReturnValue,
                OnAfterSymbolRenamedReturnValue = onAfterGlobalSymbolRenamedReturnValue
            };

            var optionService = this.Workspace.Services.GetService<IOptionService>();

            // Mock the action taken by the workspace INotificationService
            var notificationService = Workspace.Services.GetService<INotificationService>() as INotificationServiceCallback;
            var callback = new Action<string, string, NotificationSeverity>((message, title, severity) => _notificationMessage = message);
            notificationService.NotificationCallback = callback;

            var tracker = new RenameTrackingTaggerProvider(
                _historyRegistry,
                Workspace.ExportProvider.GetExport<Host.IWaitIndicator>().Value,
                Workspace.ExportProvider.GetExport<IInlineRenameService>().Value,
                Workspace.ExportProvider.GetExport<IDiagnosticAnalyzerService>().Value,
                SpecializedCollections.SingletonEnumerable(_mockRefactorNotifyService),
                Workspace.ExportProvider.GetExports<IAsynchronousOperationListener, FeatureMetadata>());

            _tagger = tracker.CreateTagger<RenameTrackingTag>(_hostDocument.GetTextBuffer());

            if (languageName == LanguageNames.CSharp)
            {
                _codeFixProvider = new CSharpRenameTrackingCodeFixProvider(
                    Workspace.ExportProvider.GetExport<Host.IWaitIndicator>().Value,
                    _historyRegistry,
                    SpecializedCollections.SingletonEnumerable(_mockRefactorNotifyService));
            }
            else if (languageName == LanguageNames.VisualBasic)
            {
                _codeFixProvider = new VisualBasicRenameTrackingCodeFixProvider(
                    Workspace.ExportProvider.GetExport<Host.IWaitIndicator>().Value,
                    _historyRegistry,
                    SpecializedCollections.SingletonEnumerable(_mockRefactorNotifyService));
            }
            else
            {
                throw new ArgumentException("Invalid langauge name: " + languageName, "languageName");
            }
        }
Esempio n. 5
0
 public TestWorkspace GetWorkspace(string markup, ExportProvider exportProvider = null, string workspaceKind = null)
 {
     if (TryParseXElement(markup, out var workspaceElement) && workspaceElement.Name == "Workspace")
     {
         _workspace       = TestWorkspace.CreateWorkspace(workspaceElement, exportProvider: exportProvider, workspaceKind: workspaceKind);
         _currentDocument = _workspace.Documents.First(d => d.CursorPosition.HasValue);
         Position         = _currentDocument.CursorPosition.Value;
         Code             = _currentDocument.GetTextBuffer().CurrentSnapshot.GetText();
         return(_workspace);
     }
     else
     {
         MarkupTestFile.GetPosition(markup.NormalizeLineEndings(), out Code, out Position);
         var workspace = GetWorkspace(exportProvider);
         _currentDocument = workspace.Documents.Single();
         return(workspace);
     }
 }
Esempio n. 6
0
        public void TestAdditionalFile_OpenClose()
        {
            using (var workspace = CreateWorkspace())
            {
                var startText = @"<setting value = ""foo""";
                var document = new TestHostDocument("public class C { }");
                var additionalDoc = new TestHostDocument(startText);
                var project1 = new TestHostProject(workspace, name: "project1", documents: new[] { document }, additionalDocuments: new[] { additionalDoc });

                workspace.AddTestProject(project1);
                var buffer = additionalDoc.GetTextBuffer();
                var doc = workspace.CurrentSolution.GetAdditionalDocument(additionalDoc.Id);
                var text = doc.GetTextAsync(CancellationToken.None).PumpingWaitResult();
                var version = doc.GetTextVersionAsync(CancellationToken.None).PumpingWaitResult();

                workspace.OnAdditionalDocumentOpened(additionalDoc.Id, additionalDoc.GetOpenTextContainer());

                // We don't have a GetOpenAdditionalDocumentIds since we don't need it. But make sure additional documents
                // don't creep into OpenDocumentIds (Bug: 1087470)
                Assert.Empty(workspace.GetOpenDocumentIds());

                workspace.OnAdditionalDocumentClosed(additionalDoc.Id, TextLoader.From(TextAndVersion.Create(text, version)));

                // Reopen and close to make sure we are not leaking anything.
                workspace.OnAdditionalDocumentOpened(additionalDoc.Id, additionalDoc.GetOpenTextContainer());
                workspace.OnAdditionalDocumentClosed(additionalDoc.Id, TextLoader.From(TextAndVersion.Create(text, version)));
                Assert.Empty(workspace.GetOpenDocumentIds());
            }
        }
Esempio n. 7
0
        public void TestAdditionalFile_DocumentChanged()
        {
            using (var workspace = CreateWorkspace())
            {
                var startText = @"<setting value = ""foo""";
                var newText = @"<setting value = ""foo1""";
                var document = new TestHostDocument("public class C { }");
                var additionalDoc = new TestHostDocument(startText);
                var project1 = new TestHostProject(workspace, name: "project1", documents: new[] { document }, additionalDocuments: new[] { additionalDoc });

                workspace.AddTestProject(project1);
                var buffer = additionalDoc.GetTextBuffer();
                workspace.OnAdditionalDocumentOpened(additionalDoc.Id, additionalDoc.GetOpenTextContainer());

                var project = workspace.CurrentSolution.Projects.Single();
                var oldVersion = project.GetSemanticVersionAsync().PumpingWaitResult();

                // fork the solution to introduce a change.
                var oldSolution = workspace.CurrentSolution;
                var newSolution = oldSolution.WithAdditionalDocumentText(additionalDoc.Id, SourceText.From(newText));
                workspace.TryApplyChanges(newSolution);

                var doc = workspace.CurrentSolution.GetAdditionalDocument(additionalDoc.Id);

                // new text should have been pushed into buffer
                Assert.Equal(newText, buffer.CurrentSnapshot.GetText());

                // Text changes are considered top level changes and they change the project's semantic version.
                Assert.Equal(doc.GetTextVersionAsync().PumpingWaitResult(), doc.GetTopLevelChangeTextVersionAsync().PumpingWaitResult());
                Assert.NotEqual(oldVersion, doc.Project.GetSemanticVersionAsync().PumpingWaitResult());
            }
        }
Esempio n. 8
0
        public void TestApplyChangesWithDocumentTextUpdated()
        {
            using (var workspace = CreateWorkspace())
            {
                var startText = "public class C { }";
                var newText = "public class D { }";

                var document = new TestHostDocument(startText);
                var project1 = new TestHostProject(workspace, document, name: "project1");

                workspace.AddTestProject(project1);
                var buffer = document.GetTextBuffer();
                workspace.OnDocumentOpened(document.Id, document.GetOpenTextContainer());

                // prove the document has the correct text
                Assert.Equal(startText, workspace.CurrentSolution.GetDocument(document.Id).GetTextAsync().PumpingWaitResult().ToString());

                // fork the solution to introduce a change.
                var oldSolution = workspace.CurrentSolution;
                var newSolution = oldSolution.WithDocumentText(document.Id, SourceText.From(newText));

                // prove that current document text is unchanged
                Assert.Equal(startText, workspace.CurrentSolution.GetDocument(document.Id).GetTextAsync().PumpingWaitResult().ToString());

                // prove buffer is unchanged too
                Assert.Equal(startText, buffer.CurrentSnapshot.GetText());

                workspace.TryApplyChanges(newSolution);

                // new text should have been pushed into buffer
                Assert.Equal(newText, buffer.CurrentSnapshot.GetText());
            }
        }
Esempio n. 9
0
        public void TestOpenAndChangeDocument()
        {
            using (var workspace = CreateWorkspace())
            {
                var solution = workspace.CurrentSolution;

                var document = new TestHostDocument(string.Empty);
                var project1 = new TestHostProject(workspace, document, name: "project1");

                workspace.AddTestProject(project1);
                var buffer = document.GetTextBuffer();
                workspace.OnDocumentOpened(document.Id, document.GetOpenTextContainer());

                buffer.Insert(0, "class C {}");

                solution = workspace.CurrentSolution;
                var doc = solution.Projects.Single().Documents.First();

                var syntaxTree = doc.GetSyntaxTreeAsync(CancellationToken.None).Result;
                Assert.True(syntaxTree.GetRoot().Width() > 0, "syntaxTree.GetRoot().Width should be > 0");

                workspace.OnDocumentClosed(document.Id);
                workspace.OnProjectRemoved(project1.Id);
            }
        }
Esempio n. 10
0
        public void TestGetCompilationOnCrossLanguageDependentProjectChangedInProgress()
        {
            using (var workspace = CreateWorkspace(disablePartialSolutions: false))
            {
                var solutionX = workspace.CurrentSolution;

                var document1 = new TestHostDocument(@"public class C { }");
                var project1 = new TestHostProject(workspace, document1, name: "project1");

                var document2 = new TestHostDocument("Public Class D \r\n  Inherits C\r\nEnd Class");
                var project2 = new TestHostProject(workspace, document2, language: LanguageNames.VisualBasic, name: "project2", projectReferences: new[] { project1 });

                workspace.AddTestProject(project1);
                workspace.AddTestProject(project2);

                var solutionY = workspace.CurrentSolution;
                var id1 = solutionY.Projects.First(p => p.Name == project1.Name).Id;
                var id2 = solutionY.Projects.First(p => p.Name == project2.Name).Id;

                var compilation2y = solutionY.GetProject(id2).GetCompilationAsync().Result;
                var errors = compilation2y.GetDiagnostics();
                var classDy = compilation2y.SourceModule.GlobalNamespace.GetTypeMembers("D").Single();
                var classCy = classDy.BaseType;
                Assert.NotEqual(TypeKind.Error, classCy.TypeKind);

                // open both documents so background compiler works on their compilations
                workspace.OnDocumentOpened(document1.Id, document1.GetOpenTextContainer());
                workspace.OnDocumentOpened(document2.Id, document2.GetOpenTextContainer());

                // change C to X
                var buffer1 = document1.GetTextBuffer();
                buffer1.Replace(new Span(13, 1), "X");

                var foundTheError = false;
                for (int iter = 0; iter < 10; iter++)
                {
                    WaitHelper.WaitForDispatchedOperationsToComplete(System.Windows.Threading.DispatcherPriority.ApplicationIdle);
                    Thread.Sleep(1000);

                    // the current solution should eventually have the change
                    var cs = workspace.CurrentSolution;
                    var doc1Z = cs.GetDocument(document1.Id);
                    var hasX = doc1Z.GetTextAsync().Result.ToString().Contains("X");

                    if (hasX)
                    {
                        var doc2Z = cs.GetDocument(document2.Id);
                        var partialDoc2Z = doc2Z.WithFrozenPartialSemanticsAsync(CancellationToken.None).Result;
                        var compilation2Z = partialDoc2Z.Project.GetCompilationAsync().Result;
                        var classDz = compilation2Z.SourceModule.GlobalNamespace.GetTypeMembers("D").Single();
                        var classCz = classDz.BaseType;

                        if (classCz.TypeKind == TypeKind.Error)
                        {
                            foundTheError = true;
                            break;
                        }
                    }
                }

                Assert.True(foundTheError, "Did not find error");
            }
        }
Esempio n. 11
0
        public void TestGetCompilationOnCrossLanguageDependentProjectChanged()
        {
            using (var workspace = CreateWorkspace())
            {
                var solutionX = workspace.CurrentSolution;

                var document1 = new TestHostDocument(@"public class C { }");
                var project1 = new TestHostProject(workspace, document1, name: "project1");

                var document2 = new TestHostDocument("Public Class D \r\n  Inherits C\r\nEnd Class");
                var project2 = new TestHostProject(workspace, document2, language: LanguageNames.VisualBasic, name: "project2", projectReferences: new[] { project1 });

                workspace.AddTestProject(project1);
                workspace.AddTestProject(project2);

                var solutionY = workspace.CurrentSolution;
                var id1 = solutionY.Projects.First(p => p.Name == project1.Name).Id;
                var id2 = solutionY.Projects.First(p => p.Name == project2.Name).Id;

                var compilation2 = solutionY.GetProject(id2).GetCompilationAsync().Result;
                var errors = compilation2.GetDiagnostics();
                var classD = compilation2.SourceModule.GlobalNamespace.GetTypeMembers("D").Single();
                var classC = classD.BaseType;
                Assert.NotEqual(TypeKind.Error, classC.TypeKind);

                // change the class name in document1
                workspace.OnDocumentOpened(document1.Id, document1.GetOpenTextContainer());
                var buffer1 = document1.GetTextBuffer();

                // change C to X
                buffer1.Replace(new Span(13, 1), "X");

                // this solution should have the change
                var solutionZ = workspace.CurrentSolution;
                var docZ = solutionZ.GetDocument(document1.Id);
                var docZText = docZ.GetTextAsync().PumpingWaitResult();

                var compilation2Z = solutionZ.GetProject(id2).GetCompilationAsync().Result;
                var classDz = compilation2Z.SourceModule.GlobalNamespace.GetTypeMembers("D").Single();
                var classCz = classDz.BaseType;

                Assert.Equal(TypeKind.Error, classCz.TypeKind);
            }
        }
Esempio n. 12
0
        public async Task TestDependentSemanticVersionChangesWhenNotOriginallyAccessed()
        {
            using (var workspace = CreateWorkspace(disablePartialSolutions: false))
            {
                var solutionX = workspace.CurrentSolution;

                var document1 = new TestHostDocument(@"public class C { }");
                var project1 = new TestHostProject(workspace, document1, name: "project1");

                var document2 = new TestHostDocument("Public Class D \r\n  Inherits C\r\nEnd Class");
                var project2 = new TestHostProject(workspace, document2, language: LanguageNames.VisualBasic, name: "project2", projectReferences: new[] { project1 });

                workspace.AddTestProject(project1);
                workspace.AddTestProject(project2);

                var solutionY = workspace.CurrentSolution;
                var id1 = solutionY.Projects.First(p => p.Name == project1.Name).Id;
                var id2 = solutionY.Projects.First(p => p.Name == project2.Name).Id;

                var compilation2y = await solutionY.GetProject(id2).GetCompilationAsync();
                var errors = compilation2y.GetDiagnostics();
                var classDy = compilation2y.SourceModule.GlobalNamespace.GetTypeMembers("D").Single();
                var classCy = classDy.BaseType;
                Assert.NotEqual(TypeKind.Error, classCy.TypeKind);

                // open both documents so background compiler works on their compilations
                workspace.OnDocumentOpened(document1.Id, document1.GetOpenTextContainer());
                workspace.OnDocumentOpened(document2.Id, document2.GetOpenTextContainer());

                // change C to X
                var buffer1 = document1.GetTextBuffer();
                buffer1.Replace(new Span(13, 1), "X");

                for (int iter = 0; iter < 10; iter++)
                {
                    WaitHelper.WaitForDispatchedOperationsToComplete(System.Windows.Threading.DispatcherPriority.ApplicationIdle);
                    Thread.Sleep(1000);

                    // the current solution should eventually have the change
                    var cs = workspace.CurrentSolution;
                    var doc1Z = cs.GetDocument(document1.Id);
                    var hasX = (await doc1Z.GetTextAsync()).ToString().Contains("X");

                    if (hasX)
                    {
                        var newVersion = await cs.GetProject(project1.Id).GetDependentSemanticVersionAsync();
                        var newVersionX = await doc1Z.Project.GetDependentSemanticVersionAsync();
                        Assert.NotEqual(VersionStamp.Default, newVersion);
                        Assert.Equal(newVersion, newVersionX);
                        break;
                    }
                }
            }
        }
        internal static IList<ITagSpan<IErrorTag>> GetErrorsFromUpdateSource(TestWorkspace workspace, TestHostDocument document, DiagnosticsUpdatedArgs updateArgs)
        {
            var source = new TestDiagnosticUpdateSource();

            var listener = new AsynchronousOperationListener();
            var listeners = AsynchronousOperationListener.CreateListeners(
                ValueTuple.Create(FeatureAttribute.DiagnosticService, listener),
                ValueTuple.Create(FeatureAttribute.ErrorSquiggles, listener));

            var optionsService = workspace.Services.GetService<IOptionService>();
            var diagnosticService = new DiagnosticService(SpecializedCollections.SingletonEnumerable<IDiagnosticUpdateSource>(source), listeners);

            var foregroundService = workspace.GetService<IForegroundNotificationService>();  //new TestForegroundNotificationService();

            var buffer = document.GetTextBuffer();
            var provider = new DiagnosticsSquiggleTaggerProvider(optionsService, diagnosticService, foregroundService, listeners);
            var tagger = provider.CreateTagger<IErrorTag>(buffer);

            source.RaiseDiagnosticsUpdated(updateArgs);

            listener.CreateWaitTask().PumpingWait();

            var snapshot = buffer.CurrentSnapshot;
            var spans = tagger.GetTags(new NormalizedSnapshotSpanCollection(new SnapshotSpan(snapshot, 0, snapshot.Length))).ToImmutableArray();

            ((IDisposable)tagger).Dispose();

            return spans;
        }