private async Task <(IDocumentAnalysis analysis, CodeAction[] diagnostics, SourceSpan insertionSpan)> GetAnalysisAndCodeActionsAndSpanAsync(
            string markup, IEnumerable <string> codes, bool enableIndexManager = false)
        {
            MarkupUtils.GetNamedSpans(markup, out var code, out var spans);

            var analysis = await GetAnalysisAsync(code);

            if (enableIndexManager)
            {
                var serviceManager = (IServiceManager)analysis.ExpressionEvaluator.Services;
                var indexManager   = new IndexManager(
                    serviceManager.GetService <IFileSystem>(),
                    analysis.Document.Interpreter.LanguageVersion,
                    rootPath: null,
                    Array.Empty <string>(),
                    Array.Empty <string>(),
                    serviceManager.GetService <IIdleTimeService>());

                // make sure index is done
                await indexManager.IndexSnapshot(analysis.Document.Interpreter.ModuleResolution.CurrentPathResolver);

                serviceManager.AddService(indexManager);
            }

            var insertionSpan = spans["insertionSpan"].First().ToSourceSpan(analysis.Ast);

            var diagnostics = GetDiagnostics(analysis, spans["diagnostic"].First().ToSourceSpan(analysis.Ast), codes);
            var codeActions = await new QuickFixCodeActionSource(analysis.ExpressionEvaluator.Services).GetCodeActionsAsync(analysis, CodeActionSettings.Default, diagnostics, TestCancellationToken);

            return(analysis, codeActions.ToArray(), insertionSpan);
        }
        private async Task TestCodeActionAsync(string markup, string title, string newText, string abbreviation, params string[] relativePaths)
        {
            MarkupUtils.GetNamedSpans(markup, out var code, out var spans);

            // get main analysis and add mock modules
            var analysis = await GetAnalysisAsync(code);

            foreach (var relativePath in relativePaths)
            {
                await GetAnalysisAsync("", analysis.ExpressionEvaluator.Services, modulePath : TestData.GetTestSpecificPath(relativePath));
            }

            // calculate actions
            var diagnosticSpan = spans["diagnostic"].First().ToSourceSpan(analysis.Ast);
            var diagnostics    = GetDiagnostics(analysis, diagnosticSpan, MissingImportCodeActionProvider.Instance.FixableDiagnostics);
            var codeActions    = await new QuickFixCodeActionSource(analysis.ExpressionEvaluator.Services).GetCodeActionsAsync(analysis, CodeActionSettings.Default, diagnostics, TestCancellationToken);

            // verify results
            var codeAction = codeActions.Single(c => c.title == title);

            codeAction.edit.changes.Should().HaveCount(1);

            var edits = codeAction.edit.changes[analysis.Document.Uri];

            edits.Should().HaveCount(2);

            var invocationEdit = edits.Single(e => e.newText == abbreviation);

            invocationEdit.range.Should().Be(diagnosticSpan);

            var insertEdit = edits.Single(e => e.newText == newText);

            insertEdit.range.Should().Be(spans["insertionSpan"].First().ToSourceSpan(analysis.Ast));
        }
        public async Task SymbolOrdering3()
        {
            var markup = @"{|insertionSpan:|}{|diagnostic:pd|}";

            MarkupUtils.GetNamedSpans(markup, out var code, out var spans);

            // get main analysis and add mock modules
            var analysis = await GetAnalysisAsync(code);

            await GetAnalysisAsync("", analysis.ExpressionEvaluator.Services, modulePath : TestData.GetTestSpecificPath("pandas.py"));
            await GetAnalysisAsync("", analysis.ExpressionEvaluator.Services, modulePath : TestData.GetTestSpecificPath("pd.py"));

            // calculate actions
            var diagnosticSpan = spans["diagnostic"].First().ToSourceSpan(analysis.Ast);
            var diagnostics    = GetDiagnostics(analysis, diagnosticSpan, MissingImportCodeActionProvider.Instance.FixableDiagnostics);
            var codeActions    = await new QuickFixCodeActionSource(analysis.ExpressionEvaluator.Services).GetCodeActionsAsync(analysis, CodeActionSettings.Default, diagnostics, TestCancellationToken);

            var list    = codeActions.Select(c => c.title).ToList();
            var zipList = Enumerable.Range(0, list.Count).Zip(list);

            var pandasIndex = zipList.First(t => t.Second == "import pandas as pd").First;
            var pdIndex     = zipList.First(t => t.Second == "import pd").First;

            pandasIndex.Should().BeLessThan(pdIndex);
        }