Exemplo n.º 1
0
        static IEnumerable <MetadataReference> GetMetadataReferences(XunitReferences references)
        {
            var result = SystemReferences;

            foreach (var kvp in ReferenceMap)
            {
                if (references.HasFlag(kvp.Key))
                {
                    result = result.Concat(kvp.Value);
                }
            }

            return(result);
        }
Exemplo n.º 2
0
        public static async Task <string> GetFixedCodeAsync(DiagnosticAnalyzer analyzer,
                                                            CodeFixProvider fixer,
                                                            string source,
                                                            CompilationReporting compilationReporting = CompilationReporting.FailOnErrors,
                                                            XunitReferences references = XunitReferences.PkgXunit,
                                                            int actionIndex            = 0)
        {
            var(compilation, document, workspace) = await GetCompilationAsync(compilationReporting, references, source);

            using (workspace)
            {
                var diagnostics = await ApplyAnalyzers(compilation, analyzer);

                if (diagnostics.Length == 0)
                {
                    throw new InvalidOperationException("The requested source code does not trigger the analyzer");
                }
                if (diagnostics.Length > 1)
                {
                    throw new InvalidOperationException($"The requested source code triggered the analyzer too many times (expected 1, got {diagnostics.Length})");
                }

                var codeActions = new List <CodeAction>();
                var context     = new CodeFixContext(document, diagnostics[0], (a, d) => codeActions.Add(a), CancellationToken.None);
                await fixer.RegisterCodeFixesAsync(context);

                if (codeActions.Count <= actionIndex)
                {
                    throw new InvalidOperationException($"Not enough code actions were registered (index {actionIndex} is out of range for length {codeActions.Count})");
                }

                var operations       = await codeActions[actionIndex].GetOperationsAsync(CancellationToken.None);
                var changeOperations = operations.OfType <ApplyChangesOperation>().ToList();
                if (changeOperations.Count != 1)
                {
                    throw new InvalidOperationException($"The change action did not yield the right number of ApplyChangesOperation objects (expected 1, got {changeOperations.Count})");
                }

                var changeOperation = changeOperations[0];
                changeOperation.Apply(workspace, CancellationToken.None);

                var solution        = changeOperation.ChangedSolution;
                var changedDocument = solution.GetDocument(document.Id);
                var text            = await changedDocument.GetTextAsync();

                return(text.ToString());
            }
        }
Exemplo n.º 3
0
 public static Task <ImmutableArray <Diagnostic> > GetDiagnosticsAsync(DiagnosticAnalyzer analyzer, XunitReferences references, string source, params string[] additionalSources)
 => GetDiagnosticsAsync(analyzer, CompilationReporting.FailOnErrors, references, source, additionalSources);
Exemplo n.º 4
0
        public static async Task <ImmutableArray <Diagnostic> > GetDiagnosticsAsync(DiagnosticAnalyzer analyzer, CompilationReporting compilationReporting, XunitReferences references, string source, params string[] additionalSources)
        {
            var(compilation, _, workspace) = await GetCompilationAsync(compilationReporting, references, source, additionalSources);

            using (workspace)
                return(await ApplyAnalyzers(compilation, analyzer));
        }
Exemplo n.º 5
0
        static async Task <(Compilation, Document, Workspace)> GetCompilationAsync(CompilationReporting compilationReporting, XunitReferences references, string source, params string[] additionalSources)
        {
            const string fileNamePrefix = "Source";
            const string projectName    = "Project";

            var projectId = ProjectId.CreateNewId(debugName: projectName);

            var workspace = new AdhocWorkspace();
            var solution  = workspace
                            .CurrentSolution
                            .AddProject(projectId, projectName, projectName, LanguageNames.CSharp)
                            .AddMetadataReferences(projectId, GetMetadataReferences(references));

            var count         = 0;
            var firstDocument = default(Document);

            foreach (var text in new[] { source }.Concat(additionalSources))
            {
                var newFileName = $"{fileNamePrefix}{count++}.cs";
                var documentId  = DocumentId.CreateNewId(projectId, debugName: newFileName);
                solution = solution.AddDocument(documentId, newFileName, SourceText.From(text));
                if (firstDocument == default(Document))
                {
                    firstDocument = solution.GetDocument(documentId);
                }
            }

            var compileWarningLevel = Math.Max(0, (int)compilationReporting);
            var project             = solution.GetProject(projectId);
            var compilationOptions  = ((CSharpCompilationOptions)project.CompilationOptions)
                                      .WithOutputKind(OutputKind.DynamicallyLinkedLibrary)
                                      .WithWarningLevel(compileWarningLevel);

            project = project.WithCompilationOptions(compilationOptions);

            var compilation = await project.GetCompilationAsync();

            if (compilationReporting != CompilationReporting.IgnoreErrors)
            {
                var compilationDiagnostics = compilation.GetDiagnostics();
                if (compilationDiagnostics.Length > 0)
                {
                    var messages = compilationDiagnostics.Select(d => (diag: d, line: d.Location.GetLineSpan().StartLinePosition))
                                   .Select(t => $"source.cs({t.line.Line},{t.line.Character}): {t.diag.Severity.ToString().ToLowerInvariant()} {t.diag.Id}: {t.diag.GetMessage()}");
                    throw new InvalidOperationException($"Compilation has issues:{Environment.NewLine}{string.Join(Environment.NewLine, messages)}");
                }
            }

            return(compilation, firstDocument, workspace);
        }