Skip to content

Commit

Permalink
Merge pull request #58427 from sharwell/inline-diags-test
Browse files Browse the repository at this point in the history
Add initial test for inline diagnostics tagger
  • Loading branch information
sharwell authored Dec 20, 2021
2 parents 421642e + d19870c commit 9a00071
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.InlineDiagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions;
using Microsoft.CodeAnalysis.Editor.UnitTests.Squiggles;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.VisualStudio.Text.Adornments;
using Microsoft.VisualStudio.Text.Tagging;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;

namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.InlineDiagnostics
{
[UseExportProvider]
public class InlineDiagnosticsTaggerProviderTests
{
[WpfFact, Trait(Traits.Feature, Traits.Features.ErrorSquiggles)]
public async Task ErrorTagGeneratedForError()
{
var spans = await GetTagSpansAsync("class C {");
Assert.Equal(1, spans.Count());

var firstSpan = spans.First();
Assert.Equal(PredefinedErrorTypeNames.SyntaxError, firstSpan.Tag.ErrorType);
}

private static async Task<ImmutableArray<ITagSpan<InlineDiagnosticsTag>>> GetTagSpansAsync(string content)
{
using var workspace = TestWorkspace.CreateCSharp(content, composition: SquiggleUtilities.WpfCompositionWithSolutionCrawler);
return await GetTagSpansAsync(workspace);
}

private static async Task<ImmutableArray<ITagSpan<InlineDiagnosticsTag>>> GetTagSpansAsync(TestWorkspace workspace)
{
workspace.ApplyOptions(new[] { KeyValuePairUtil.Create(new OptionKey2(InlineDiagnosticsOptions.EnableInlineDiagnostics, LanguageNames.CSharp), (object)true) });
return (await TestDiagnosticTagProducer<InlineDiagnosticsTaggerProvider, InlineDiagnosticsTag>.GetDiagnosticsAndErrorSpans(workspace)).Item2;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ void Test()
</Workspace>";

using var workspace = TestWorkspace.Create(workspaceXml);
var spans = (await TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider>.GetDiagnosticsAndErrorSpans(workspace)).Item2;
var spans = (await TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider, IErrorTag>.GetDiagnosticsAndErrorSpans(workspace)).Item2;

Assert.Equal(1, spans.Count());
Assert.Equal(PredefinedErrorTypeNames.SyntaxError, spans.First().Tag.ErrorType);
Expand Down Expand Up @@ -126,7 +126,7 @@ void Test()
}
};

var diagnosticsAndSpans = await TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider>.GetDiagnosticsAndErrorSpans(workspace, analyzerMap);
var diagnosticsAndSpans = await TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider, IErrorTag>.GetDiagnosticsAndErrorSpans(workspace, analyzerMap);

var spans =
diagnosticsAndSpans.Item1
Expand Down Expand Up @@ -204,7 +204,7 @@ public async Task SemanticErrorReported()
{
using var workspace = TestWorkspace.CreateCSharp("class C : Bar { }", composition: SquiggleUtilities.CompositionWithSolutionCrawler);

var spans = await TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider>.GetDiagnosticsAndErrorSpans(workspace);
var spans = await TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider, IErrorTag>.GetDiagnosticsAndErrorSpans(workspace);

Assert.Equal(1, spans.Item2.Count());

Expand Down Expand Up @@ -296,10 +296,10 @@ class Test
var updateArgs = DiagnosticsUpdatedArgs.DiagnosticsCreated(
new object(), workspace, workspace.CurrentSolution, document.Project.Id, document.Id,
ImmutableArray.Create(
TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider>.CreateDiagnosticData(document, new TextSpan(0, 0)),
TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider>.CreateDiagnosticData(document, new TextSpan(0, 1))));
TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider, IErrorTag>.CreateDiagnosticData(document, new TextSpan(0, 0)),
TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider, IErrorTag>.CreateDiagnosticData(document, new TextSpan(0, 1))));

var spans = await TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider>.GetErrorsFromUpdateSource(workspace, updateArgs);
var spans = await TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider, IErrorTag>.GetErrorsFromUpdateSource(workspace, updateArgs);

Assert.Equal(1, spans.Count());
var first = spans.First();
Expand Down Expand Up @@ -327,10 +327,10 @@ class Test
var updateArgs = DiagnosticsUpdatedArgs.DiagnosticsCreated(
new LiveId(), workspace, workspace.CurrentSolution, document.Project.Id, document.Id,
ImmutableArray.Create(
TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider>.CreateDiagnosticData(document, new TextSpan(0, 0)),
TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider>.CreateDiagnosticData(document, new TextSpan(0, 1))));
TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider, IErrorTag>.CreateDiagnosticData(document, new TextSpan(0, 0)),
TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider, IErrorTag>.CreateDiagnosticData(document, new TextSpan(0, 1))));

var spans = await TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider>.GetErrorsFromUpdateSource(workspace, updateArgs);
var spans = await TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider, IErrorTag>.GetErrorsFromUpdateSource(workspace, updateArgs);

Assert.Equal(2, spans.Count());
var first = spans.First();
Expand All @@ -350,7 +350,7 @@ public LiveId()
private static async Task<ImmutableArray<ITagSpan<IErrorTag>>> GetTagSpansAsync(string content)
{
using var workspace = TestWorkspace.CreateCSharp(content, composition: SquiggleUtilities.CompositionWithSolutionCrawler);
return (await TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider>.GetDiagnosticsAndErrorSpans(workspace)).Item2;
return (await TestDiagnosticTagProducer<DiagnosticsSquiggleTaggerProvider, IErrorTag>.GetDiagnosticsAndErrorSpans(workspace)).Item2;
}

private sealed class ReportOnClassWithLink : DiagnosticAnalyzer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void M() {
{ LanguageNames.CSharp, ImmutableArray.Create<DiagnosticAnalyzer>(new CSharpUseObjectInitializerDiagnosticAnalyzer()) }
};

var spans = (await TestDiagnosticTagProducer<DiagnosticsSuggestionTaggerProvider>.GetDiagnosticsAndErrorSpans(workspace, analyzerMap)).Item2;
var spans = (await TestDiagnosticTagProducer<DiagnosticsSuggestionTaggerProvider, IErrorTag>.GetDiagnosticsAndErrorSpans(workspace, analyzerMap)).Item2;
return (spans, workspace.Documents.Single().SelectedSpans.Single());
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public async Task TestPreviewDiagnosticTagger()
// enable preview diagnostics
previewWorkspace.EnableDiagnostic();

var diagnosticsAndErrorsSpans = await SquiggleUtilities.GetDiagnosticsAndErrorSpansAsync<DiagnosticsSquiggleTaggerProvider>(workspace);
var diagnosticsAndErrorsSpans = await SquiggleUtilities.GetDiagnosticsAndErrorSpansAsync<DiagnosticsSquiggleTaggerProvider, IErrorTag>(workspace);
const string AnalyzerCount = "Analyzer Count: ";
Assert.Equal(AnalyzerCount + 1, AnalyzerCount + diagnosticsAndErrorsSpans.Item1.Length);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics;
using Microsoft.CodeAnalysis.Editor.InlineDiagnostics;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Shared.TestHooks;
Expand Down Expand Up @@ -76,7 +77,8 @@ public ITaggerProvider TaggerProvider

if (typeof(TProvider) == typeof(DiagnosticsSquiggleTaggerProvider)
|| typeof(TProvider) == typeof(DiagnosticsSuggestionTaggerProvider)
|| typeof(TProvider) == typeof(DiagnosticsClassificationTaggerProvider))
|| typeof(TProvider) == typeof(DiagnosticsClassificationTaggerProvider)
|| typeof(TProvider) == typeof(InlineDiagnosticsTaggerProvider))
{
_taggerProvider = _workspace.ExportProvider.GetExportedValues<ITaggerProvider>()
.OfType<TProvider>()
Expand Down
12 changes: 8 additions & 4 deletions src/EditorFeatures/TestUtilities/Squiggles/SquiggleUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,17 @@ public static class SquiggleUtilities
internal static TestComposition CompositionWithSolutionCrawler = EditorTestCompositions.EditorFeatures
.RemoveParts(typeof(MockWorkspaceEventListenerProvider));

internal static async Task<(ImmutableArray<DiagnosticData>, ImmutableArray<ITagSpan<IErrorTag>>)> GetDiagnosticsAndErrorSpansAsync<TProvider>(
internal static TestComposition WpfCompositionWithSolutionCrawler = EditorTestCompositions.EditorFeaturesWpf
.RemoveParts(typeof(MockWorkspaceEventListenerProvider));

internal static async Task<(ImmutableArray<DiagnosticData>, ImmutableArray<ITagSpan<TTag>>)> GetDiagnosticsAndErrorSpansAsync<TProvider, TTag>(
TestWorkspace workspace,
IReadOnlyDictionary<string, ImmutableArray<DiagnosticAnalyzer>> analyzerMap = null)
where TProvider : AbstractDiagnosticsAdornmentTaggerProvider<IErrorTag>
where TProvider : AbstractDiagnosticsAdornmentTaggerProvider<TTag>
where TTag : class, ITag
{
using var wrapper = new DiagnosticTaggerWrapper<TProvider, IErrorTag>(workspace, analyzerMap);
var tagger = wrapper.TaggerProvider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer());
using var wrapper = new DiagnosticTaggerWrapper<TProvider, TTag>(workspace, analyzerMap);
var tagger = wrapper.TaggerProvider.CreateTagger<TTag>(workspace.Documents.First().GetTextBuffer());

using var disposable = tagger as IDisposable;
await wrapper.WaitForTags();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,25 @@

namespace Microsoft.CodeAnalysis.Editor.UnitTests.Squiggles
{
internal sealed class TestDiagnosticTagProducer<TProvider>
where TProvider : AbstractDiagnosticsAdornmentTaggerProvider<IErrorTag>
internal sealed class TestDiagnosticTagProducer<TProvider, TTag>
where TProvider : AbstractDiagnosticsAdornmentTaggerProvider<TTag>
where TTag : class, ITag
{
internal static Task<(ImmutableArray<DiagnosticData>, ImmutableArray<ITagSpan<IErrorTag>>)> GetDiagnosticsAndErrorSpans(
internal static Task<(ImmutableArray<DiagnosticData>, ImmutableArray<ITagSpan<TTag>>)> GetDiagnosticsAndErrorSpans(
TestWorkspace workspace,
IReadOnlyDictionary<string, ImmutableArray<DiagnosticAnalyzer>> analyzerMap = null)
{
return SquiggleUtilities.GetDiagnosticsAndErrorSpansAsync<TProvider>(workspace, analyzerMap);
return SquiggleUtilities.GetDiagnosticsAndErrorSpansAsync<TProvider, TTag>(workspace, analyzerMap);
}

internal static async Task<IList<ITagSpan<IErrorTag>>> GetErrorsFromUpdateSource(TestWorkspace workspace, DiagnosticsUpdatedArgs updateArgs)
internal static async Task<IList<ITagSpan<TTag>>> GetErrorsFromUpdateSource(TestWorkspace workspace, DiagnosticsUpdatedArgs updateArgs)
{
var globalOptions = workspace.GetService<IGlobalOptionService>();
var source = new TestDiagnosticUpdateSource(globalOptions);

using var wrapper = new DiagnosticTaggerWrapper<TProvider, IErrorTag>(workspace, updateSource: source);
using var wrapper = new DiagnosticTaggerWrapper<TProvider, TTag>(workspace, updateSource: source);

var tagger = wrapper.TaggerProvider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer());
var tagger = wrapper.TaggerProvider.CreateTagger<TTag>(workspace.Documents.First().GetTextBuffer());
using var disposable = (IDisposable)tagger;

source.RaiseDiagnosticsUpdated(updateArgs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Squiggles

Private Shared Async Function ProduceSquiggles(content As String) As Task(Of ImmutableArray(Of ITagSpan(Of IErrorTag)))
Using workspace = TestWorkspace.CreateVisualBasic(content)
Return (Await TestDiagnosticTagProducer(Of DiagnosticsSquiggleTaggerProvider).GetDiagnosticsAndErrorSpans(workspace)).Item2
Return (Await TestDiagnosticTagProducer(Of DiagnosticsSquiggleTaggerProvider, IErrorTag).GetDiagnosticsAndErrorSpans(workspace)).Item2
End Using
End Function

Expand Down Expand Up @@ -68,7 +68,7 @@ End Class")
End Sub
End Class")

Dim diagnosticsAndSpans = Await TestDiagnosticTagProducer(Of DiagnosticsSquiggleTaggerProvider).GetDiagnosticsAndErrorSpans(workspace)
Dim diagnosticsAndSpans = Await TestDiagnosticTagProducer(Of DiagnosticsSquiggleTaggerProvider, IErrorTag).GetDiagnosticsAndErrorSpans(workspace)
Dim spans = diagnosticsAndSpans.Item1.Zip(diagnosticsAndSpans.Item2, Function(diagostic, span) (diagostic, span)).OrderBy(Function(s) s.span.Span.Span.Start).ToImmutableArray()

Assert.Equal(1, spans.Count())
Expand Down Expand Up @@ -122,7 +122,7 @@ End Class"
options.Add(preferIntrinsicPredefinedTypeOption, preferIntrinsicPredefinedTypeOptionValue)
workspace.ApplyOptions(options)

Dim diagnosticsAndSpans = Await TestDiagnosticTagProducer(Of DiagnosticsSquiggleTaggerProvider).GetDiagnosticsAndErrorSpans(workspace, analyzerMap)
Dim diagnosticsAndSpans = Await TestDiagnosticTagProducer(Of DiagnosticsSquiggleTaggerProvider, IErrorTag).GetDiagnosticsAndErrorSpans(workspace, analyzerMap)
Dim spans = diagnosticsAndSpans.Item1.Zip(diagnosticsAndSpans.Item2, Function(diagostic, span) (diagostic, span)).OrderBy(Function(s) s.span.Span.Span.Start).ToImmutableArray()

Assert.Equal(2, spans.Length)
Expand Down

0 comments on commit 9a00071

Please sign in to comment.